/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL ES 3.1 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 Texture level state query tests
 *//*--------------------------------------------------------------------*/

#include "es31fTextureLevelStateQueryTests.hpp"
#include "glsStateQueryUtil.hpp"
#include "tcuTestLog.hpp"
#include "gluRenderContext.hpp"
#include "gluCallLogWrapper.hpp"
#include "gluTextureUtil.hpp"
#include "gluStrUtil.hpp"
#include "gluContextInfo.hpp"
#include "glwFunctions.hpp"
#include "glwEnums.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuFormatUtil.hpp"
#include "deStringUtil.hpp"
#include "deUniquePtr.hpp"

namespace deqp
{
namespace gles31
{
namespace Functional
{
namespace
{

using namespace gls::StateQueryUtil;


static bool textureTypeHasDepth (glw::GLenum textureBindTarget)
{
	switch (textureBindTarget)
	{
		case GL_TEXTURE_2D:						return false;
		case GL_TEXTURE_3D:						return true;
		case GL_TEXTURE_2D_ARRAY:				return true;
		case GL_TEXTURE_CUBE_MAP:				return false;
		case GL_TEXTURE_2D_MULTISAMPLE:			return false;
		case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:	return true;
		case GL_TEXTURE_BUFFER:					return false;
		case GL_TEXTURE_CUBE_MAP_ARRAY:			return true;
		default:
			DE_ASSERT(DE_FALSE);
			return false;
	}
}

static bool textureTypeHasHeight (glw::GLenum textureBindTarget)
{
	switch (textureBindTarget)
	{
		case GL_TEXTURE_2D:						return true;
		case GL_TEXTURE_3D:						return true;
		case GL_TEXTURE_2D_ARRAY:				return true;
		case GL_TEXTURE_CUBE_MAP:				return true;
		case GL_TEXTURE_2D_MULTISAMPLE:			return true;
		case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:	return true;
		case GL_TEXTURE_BUFFER:					return false;
		case GL_TEXTURE_CUBE_MAP_ARRAY:			return true;
		default:
			DE_ASSERT(DE_FALSE);
			return false;
	}
}

static const char* getTextureTargetExtension (glw::GLenum target)
{
	switch (target)
	{
		case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:	return "GL_OES_texture_storage_multisample_2d_array";
		case GL_TEXTURE_BUFFER:					return "GL_EXT_texture_buffer";
		case GL_TEXTURE_CUBE_MAP_ARRAY:			return "GL_EXT_texture_cube_map_array";
		default:
			DE_ASSERT(DE_FALSE);
			return DE_NULL;
	}
}

static bool isCoreTextureTarget (glw::GLenum target)
{
	switch (target)
	{
		case GL_TEXTURE_2D:
		case GL_TEXTURE_3D:
		case GL_TEXTURE_2D_ARRAY:
		case GL_TEXTURE_CUBE_MAP:
		case GL_TEXTURE_2D_MULTISAMPLE:
			return true;

		default:
			return false;
	}
}

struct TextureGenerationSpec
{
	struct TextureLevelSpec
	{
		int			width;
		int			height;
		int			depth;
		int			level;
		glw::GLenum internalFormat;
		bool		compressed;

		TextureLevelSpec (void)
			: width				(0)
			, height			(0)
			, depth				(0)
			, level				(0)
			, internalFormat	(GL_RGBA)
			, compressed		(false)
		{
		}
	};

	glw::GLenum						bindTarget;
	glw::GLenum						queryTarget;
	bool							immutable;
	bool							fixedSamplePos;	// !< fixed sample pos argument for multisample textures
	int								sampleCount;
	int								texBufferDataOffset;
	int								texBufferDataSize;
	bool							bindWholeArray;
	std::vector<TextureLevelSpec>	levels;
	std::string						description;

	TextureGenerationSpec (void)
		: immutable				(true)
		, fixedSamplePos		(true)
		, sampleCount			(0)
		, texBufferDataOffset	(0)
		, texBufferDataSize		(256)
		, bindWholeArray		(false)
	{
	}
};
struct IntegerPrinter
{
	static std::string	getIntegerName	(int v)		{ return de::toString(v); }
	static std::string	getFloatName	(float v)	{ return de::toString(v); }
};

struct PixelFormatPrinter
{
	static std::string	getIntegerName	(int v)		{ return de::toString(glu::getPixelFormatStr(v));		}
	static std::string	getFloatName	(float v)	{ return de::toString(glu::getPixelFormatStr((int)v));	}
};

template <typename Printer>
static bool verifyTextureLevelParameterEqualWithPrinter (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, QueryType type)
{
	QueriedState			state;
	tcu::ResultCollector	result	(gl.getLog(), " // ERROR: ");

	gl.getLog() << tcu::TestLog::Message << "Verifying " << glu::getTextureLevelParameterStr(pname) << ", expecting " << Printer::getIntegerName(refValue) << tcu::TestLog::EndMessage;
	queryTextureLevelState(result, gl, type, target, level, pname, state);

	if (state.isUndefined())
		return false;

	verifyInteger(result, state, refValue);

	return result.getResult() == QP_TEST_RESULT_LAST;
}

static bool verifyTextureLevelParameterEqual (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, QueryType type)
{
	return verifyTextureLevelParameterEqualWithPrinter<IntegerPrinter>(gl, target, level, pname, refValue, type);
}

static bool verifyTextureLevelParameterInternalFormatEqual (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, QueryType type)
{
	return verifyTextureLevelParameterEqualWithPrinter<PixelFormatPrinter>(gl, target, level, pname, refValue, type);
}

static bool verifyTextureLevelParameterGreaterOrEqual (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, QueryType type)
{
	QueriedState			state;
	tcu::ResultCollector	result	(gl.getLog(), " // ERROR: ");

	gl.getLog() << tcu::TestLog::Message << "Verifying " << glu::getTextureLevelParameterStr(pname) << ", expecting " << refValue << " or greater" << tcu::TestLog::EndMessage;
	queryTextureLevelState(result, gl, type, target, level, pname, state);

	if (state.isUndefined())
		return false;

	verifyIntegerMin(result, state, refValue);

	return result.getResult() == QP_TEST_RESULT_LAST;
}

static bool verifyTextureLevelParameterInternalFormatAnyOf (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, const int* refValues, int numRefValues, QueryType type)
{
	QueriedState			state;
	tcu::ResultCollector	result	(gl.getLog(), " // ERROR: ");

	// Log what we try to do
	{
		tcu::MessageBuilder msg(&gl.getLog());

		msg << "Verifying " << glu::getTextureLevelParameterStr(pname) << ", expecting any of {";
		for (int ndx = 0; ndx < numRefValues; ++ndx)
		{
			if (ndx != 0)
				msg << ", ";
			msg << glu::getPixelFormatStr(refValues[ndx]);
		}
		msg << "}";
		msg << tcu::TestLog::EndMessage;
	}

	queryTextureLevelState(result, gl, type, target, level, pname, state);
	if (state.isUndefined())
		return false;

	// verify
	switch (state.getType())
	{
		case DATATYPE_INTEGER:
		{
			for (int ndx = 0; ndx < numRefValues; ++ndx)
				if (state.getIntAccess() == refValues[ndx])
					return true;

			gl.getLog() << tcu::TestLog::Message << "Error: got " << state.getIntAccess() << ", (" << glu::getPixelFormatStr(state.getIntAccess()) << ")" << tcu::TestLog::EndMessage;
			return false;
		}
		case DATATYPE_FLOAT:
		{
			for (int ndx = 0; ndx < numRefValues; ++ndx)
				if (state.getFloatAccess() == (float)refValues[ndx])
					return true;

			gl.getLog() << tcu::TestLog::Message << "Error: got " << state.getFloatAccess() << ", (" << glu::getPixelFormatStr((int)state.getFloatAccess()) << ")" << tcu::TestLog::EndMessage;
			return false;
		}
		default:
			DE_ASSERT(DE_FALSE);
			return false;
	}
}

static bool isDepthFormat (const tcu::TextureFormat& fmt)
{
	return fmt.order == tcu::TextureFormat::D || fmt.order == tcu::TextureFormat::DS;
}

static bool isColorRenderableFormat (glw::GLenum internalFormat)
{
	return	internalFormat == GL_RGB565			||
			internalFormat == GL_RGBA4			||
			internalFormat == GL_RGB5_A1		||
			internalFormat == GL_RGB10_A2		||
			internalFormat == GL_RGB10_A2UI		||
			internalFormat == GL_SRGB8_ALPHA8	||
			internalFormat == GL_R8				||
			internalFormat == GL_RG8			||
			internalFormat == GL_RGB8			||
			internalFormat == GL_RGBA8			||
			internalFormat == GL_R8I			||
			internalFormat == GL_RG8I			||
			internalFormat == GL_RGBA8I			||
			internalFormat == GL_R8UI			||
			internalFormat == GL_RG8UI			||
			internalFormat == GL_RGBA8UI		||
			internalFormat == GL_R16I			||
			internalFormat == GL_RG16I			||
			internalFormat == GL_RGBA16I		||
			internalFormat == GL_R16UI			||
			internalFormat == GL_RG16UI			||
			internalFormat == GL_RGBA16UI		||
			internalFormat == GL_R32I			||
			internalFormat == GL_RG32I			||
			internalFormat == GL_RGBA32I		||
			internalFormat == GL_R32UI			||
			internalFormat == GL_RG32UI			||
			internalFormat == GL_RGBA32UI;
}

static bool isRenderableFormat (glw::GLenum internalFormat)
{
	return	isColorRenderableFormat(internalFormat)	||
			internalFormat == GL_DEPTH_COMPONENT16	||
			internalFormat == GL_DEPTH_COMPONENT24	||
			internalFormat == GL_DEPTH_COMPONENT32F	||
			internalFormat == GL_DEPTH24_STENCIL8	||
			internalFormat == GL_DEPTH32F_STENCIL8;
}

static bool isTextureBufferFormat (glw::GLenum internalFormat)
{
	return	internalFormat == GL_R8			||
			internalFormat == GL_R16F		||
			internalFormat == GL_R32F		||
			internalFormat == GL_R8I		||
			internalFormat == GL_R16I		||
			internalFormat == GL_R32I		||
			internalFormat == GL_R8UI		||
			internalFormat == GL_R16UI		||
			internalFormat == GL_R32UI		||
			internalFormat == GL_RG8		||
			internalFormat == GL_RG16F		||
			internalFormat == GL_RG32F		||
			internalFormat == GL_RG8I		||
			internalFormat == GL_RG16I		||
			internalFormat == GL_RG32I		||
			internalFormat == GL_RG8UI		||
			internalFormat == GL_RG16UI		||
			internalFormat == GL_RG32UI		||
			internalFormat == GL_RGB32F		||
			internalFormat == GL_RGB32I		||
			internalFormat == GL_RGB32UI	||
			internalFormat == GL_RGBA8		||
			internalFormat == GL_RGBA16F	||
			internalFormat == GL_RGBA32F	||
			internalFormat == GL_RGBA8I		||
			internalFormat == GL_RGBA16I	||
			internalFormat == GL_RGBA32I	||
			internalFormat == GL_RGBA8UI	||
			internalFormat == GL_RGBA16UI	||
			internalFormat == GL_RGBA32UI;
}

static bool isLegalFormatForTarget (glw::GLenum target, glw::GLenum format)
{
	const tcu::TextureFormat fmt = glu::mapGLInternalFormat(format);

	if (target == GL_TEXTURE_3D && isDepthFormat(fmt))
		return false;
	if ((target == GL_TEXTURE_2D_MULTISAMPLE || target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) && !isRenderableFormat(format))
		return false;
	if (target == GL_TEXTURE_BUFFER || !isTextureBufferFormat(format))
		return false;
	return true;
}

static bool isCompressionSupportedForTarget (glw::GLenum target)
{
	return target == GL_TEXTURE_2D || target == GL_TEXTURE_2D_ARRAY;
}

static bool isMultisampleTarget (glw::GLenum target)
{
	return target == GL_TEXTURE_2D_MULTISAMPLE || target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
}

static bool targetSupportsMipLevels (glw::GLenum target)
{
	return	target != GL_TEXTURE_2D_MULTISAMPLE &&
			target != GL_TEXTURE_2D_MULTISAMPLE_ARRAY &&
			target != GL_TEXTURE_BUFFER;
}

static int getPixelSize (glw::GLenum internalFormat)
{
	const tcu::TextureFormat fmt = glu::mapGLInternalFormat(internalFormat);
	return fmt.getPixelSize();
}

static void generateColorTextureGenerationGroup (std::vector<TextureGenerationSpec>& group, glw::GLenum target, int maxSamples, glw::GLenum internalFormat)
{
	const glw::GLenum queryTarget = (target == GL_TEXTURE_CUBE_MAP) ? (GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) : (target);

	// initial
	{
		TextureGenerationSpec texGen;
		texGen.bindTarget		= target;
		texGen.queryTarget		= queryTarget;
		texGen.immutable		= true;
		texGen.sampleCount		= 0;
		texGen.description		= glu::getTextureTargetStr(target).toString() + ", initial values";

		group.push_back(texGen);
	}

	// ms targets
	if (isMultisampleTarget(target))
	{
		{
			TextureGenerationSpec					texGen;
			TextureGenerationSpec::TextureLevelSpec	level;

			texGen.bindTarget		= target;
			texGen.queryTarget		= queryTarget;
			texGen.immutable		= true;
			texGen.sampleCount		= 1;
			texGen.fixedSamplePos	= false;
			texGen.description		= glu::getTextureTargetStr(target).toString() + ", low sample count";

			level.width				= 16;
			level.height			= 16;
			level.depth				= (textureTypeHasDepth(texGen.bindTarget)) ? (6) : (1);
			level.level				= 0;
			level.internalFormat	= internalFormat;
			level.compressed		= false;

			texGen.levels.push_back(level);
			group.push_back(texGen);
		}
		{
			TextureGenerationSpec					texGen;
			TextureGenerationSpec::TextureLevelSpec	level;

			texGen.bindTarget		= target;
			texGen.queryTarget		= queryTarget;
			texGen.immutable		= true;
			texGen.sampleCount		= maxSamples;
			texGen.fixedSamplePos	= false;
			texGen.description		= glu::getTextureTargetStr(target).toString() + ", high sample count";

			level.width				= 32;
			level.height			= 32;
			level.depth				= (textureTypeHasDepth(texGen.bindTarget)) ? (6) : (1);
			level.level				= 0;
			level.internalFormat	= internalFormat;
			level.compressed		= false;

			texGen.levels.push_back(level);
			group.push_back(texGen);
		}
		{
			TextureGenerationSpec					texGen;
			TextureGenerationSpec::TextureLevelSpec	level;

			texGen.bindTarget		= target;
			texGen.queryTarget		= queryTarget;
			texGen.immutable		= true;
			texGen.sampleCount		= maxSamples;
			texGen.fixedSamplePos	= true;
			texGen.description		= glu::getTextureTargetStr(target).toString() + ", fixed sample positions";

			level.width				= 32;
			level.height			= 32;
			level.depth				= (textureTypeHasDepth(texGen.bindTarget)) ? (6) : (1);
			level.level				= 0;
			level.internalFormat	= internalFormat;
			level.compressed		= false;

			texGen.levels.push_back(level);
			group.push_back(texGen);
		}
	}
	else if (target == GL_TEXTURE_BUFFER)
	{
		// whole buffer
		{
			TextureGenerationSpec					texGen;
			TextureGenerationSpec::TextureLevelSpec	level;
			const int								baseSize = getPixelSize(internalFormat);

			texGen.bindTarget			= target;
			texGen.queryTarget			= queryTarget;
			texGen.immutable			= true;
			texGen.description			= glu::getTextureTargetStr(target).toString() + ", whole buffer";
			texGen.texBufferDataOffset	= 0;
			texGen.texBufferDataSize	= 32 * baseSize + (baseSize - 1);
			texGen.bindWholeArray		= true;

			level.width				= 32;
			level.height			= 1;
			level.depth				= 1;
			level.level				= 0;
			level.internalFormat	= internalFormat;
			level.compressed		= false;

			texGen.levels.push_back(level);
			group.push_back(texGen);
		}
		// partial buffer
		{
			TextureGenerationSpec					texGen;
			TextureGenerationSpec::TextureLevelSpec	level;
			const int								baseSize = getPixelSize(internalFormat);

			texGen.bindTarget			= target;
			texGen.queryTarget			= queryTarget;
			texGen.immutable			= true;
			texGen.description			= glu::getTextureTargetStr(target).toString() + ", partial buffer";
			texGen.texBufferDataOffset	= 256;
			texGen.texBufferDataSize	= 16 * baseSize + (baseSize - 1);
			texGen.bindWholeArray		= false;

			level.width				= 16;
			level.height			= 1;
			level.depth				= 1;
			level.level				= 0;
			level.internalFormat	= internalFormat;
			level.compressed		= false;

			texGen.levels.push_back(level);
			group.push_back(texGen);
		}
	}
	else
	{
		// immutable
		{
			TextureGenerationSpec					texGen;
			TextureGenerationSpec::TextureLevelSpec	level;

			texGen.bindTarget		= target;
			texGen.queryTarget		= queryTarget;
			texGen.immutable		= true;
			texGen.description		= glu::getTextureTargetStr(target).toString() + ", immutable";

			level.width				= 32;
			level.height			= 32;
			level.depth				= (textureTypeHasDepth(texGen.bindTarget)) ? (6) : (1);
			level.level				= 0;
			level.internalFormat	= internalFormat;
			level.compressed		= false;

			texGen.levels.push_back(level);
			group.push_back(texGen);
		}
		// mutable
		{
			TextureGenerationSpec					texGen;
			TextureGenerationSpec::TextureLevelSpec	level;

			texGen.bindTarget		= target;
			texGen.queryTarget		= queryTarget;
			texGen.immutable		= false;
			texGen.description		= glu::getTextureTargetStr(target).toString() + ", mutable";

			level.width				= 16;
			level.height			= (target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY) ? (16) : (64);
			level.depth				= (textureTypeHasDepth(texGen.bindTarget)) ? (6) : (1);
			level.level				= 0;
			level.internalFormat	= internalFormat;
			level.compressed		= false;

			texGen.levels.push_back(level);
			group.push_back(texGen);
		}
		// mip3
		{
			TextureGenerationSpec					texGen;
			TextureGenerationSpec::TextureLevelSpec	level;

			texGen.bindTarget		= target;
			texGen.queryTarget		= queryTarget;
			texGen.immutable		= false;
			texGen.description		= glu::getTextureTargetStr(target).toString() + ", mip level 3";

			level.width				= 4;
			level.height			= (target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_CUBE_MAP_ARRAY) ? (4) : (8);
			level.depth				= (textureTypeHasDepth(texGen.bindTarget)) ? (6) : (1);
			level.level				= 3;
			level.internalFormat	= internalFormat;
			level.compressed		= false;

			texGen.levels.push_back(level);
			group.push_back(texGen);
		}
	}
}

static void generateInternalFormatTextureGenerationGroup (std::vector<TextureGenerationSpec>& group, glw::GLenum target)
{
	const glw::GLenum queryTarget = (target == GL_TEXTURE_CUBE_MAP) ? (GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) : (target);

	// Internal formats
	static const glw::GLenum internalFormats[] =
	{
		GL_R8, GL_R8_SNORM, GL_RG8, GL_RG8_SNORM, GL_RGB8, GL_RGB8_SNORM, GL_RGB565, GL_RGBA4, GL_RGB5_A1,
		GL_RGBA8, GL_RGBA8_SNORM, GL_RGB10_A2, GL_RGB10_A2UI, GL_SRGB8, GL_SRGB8_ALPHA8, GL_R16F, GL_RG16F,
		GL_RGB16F, GL_RGBA16F, GL_R32F, GL_RG32F, GL_RGB32F, GL_RGBA32F, GL_R11F_G11F_B10F, GL_RGB9_E5, GL_R8I,
		GL_R8UI, GL_R16I, GL_R16UI, GL_R32I, GL_R32UI, GL_RG8I, GL_RG8UI, GL_RG16I, GL_RG16UI, GL_RG32I, GL_RG32UI,
		GL_RGB8I, GL_RGB8UI, GL_RGB16I, GL_RGB16UI, GL_RGB32I, GL_RGB32UI, GL_RGBA8I, GL_RGBA8UI, GL_RGBA16I,
		GL_RGBA16UI, GL_RGBA32I, GL_RGBA32UI,

		GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16,
		GL_DEPTH32F_STENCIL8, GL_DEPTH24_STENCIL8
	};

	// initial
	{
		TextureGenerationSpec texGen;
		texGen.bindTarget		= target;
		texGen.queryTarget		= queryTarget;
		texGen.immutable		= true;
		texGen.sampleCount		= 0;
		texGen.fixedSamplePos	= true;
		texGen.description		= glu::getTextureTargetStr(target).toString() + ", initial values";

		group.push_back(texGen);
	}

	// test all formats
	for (int internalFormatNdx = 0; internalFormatNdx < DE_LENGTH_OF_ARRAY(internalFormats); ++internalFormatNdx)
	{
		if (!isLegalFormatForTarget(target, internalFormats[internalFormatNdx]))
			continue;

		const int								baseSize = getPixelSize(internalFormats[internalFormatNdx]);
		TextureGenerationSpec					texGen;
		TextureGenerationSpec::TextureLevelSpec	level;

		texGen.bindTarget		= target;
		texGen.queryTarget		= queryTarget;
		texGen.immutable		= true;
		texGen.sampleCount		= (isMultisampleTarget(target) ? (1) : (0));
		texGen.description		= glu::getTextureTargetStr(target).toString() + ", internal format " + glu::getPixelFormatName(internalFormats[internalFormatNdx]);

		if (target == GL_TEXTURE_BUFFER)
		{
			texGen.texBufferDataOffset	= 0;
			texGen.texBufferDataSize	= 32 * baseSize + (baseSize - 1);
			texGen.bindWholeArray		= true;
		}

		level.width				= 32;
		level.height			= (textureTypeHasHeight(target)) ? (32) : (1);
		level.depth				= (textureTypeHasDepth(target)) ? (6) : (1);
		level.level				= 0;
		level.internalFormat	= internalFormats[internalFormatNdx];
		level.compressed		= false;

		texGen.levels.push_back(level);
		group.push_back(texGen);
	}

	// test mutable rgba8 with mip level 3
	if (targetSupportsMipLevels(target))
	{
		TextureGenerationSpec					texGen;
		TextureGenerationSpec::TextureLevelSpec	level;

		texGen.bindTarget		= target;
		texGen.queryTarget		= queryTarget;
		texGen.immutable		= false;
		texGen.description		= glu::getTextureTargetStr(target).toString() + ", internal format GL_RGBA8, mip level 3";

		level.width				= 32;
		level.height			= 32;
		level.depth				= (textureTypeHasDepth(target)) ? (6) : (1);
		level.level				= 3;
		level.internalFormat	= GL_RGBA8;
		level.compressed		= false;

		texGen.levels.push_back(level);
		group.push_back(texGen);
	}
}

static void generateCompressedTextureGenerationGroup (std::vector<TextureGenerationSpec>& group, glw::GLenum target)
{
	const glw::GLenum queryTarget = (target == GL_TEXTURE_CUBE_MAP) ? (GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) : (target);

	// initial
	{
		TextureGenerationSpec texGen;
		texGen.bindTarget	= target;
		texGen.queryTarget	= queryTarget;
		texGen.immutable	= true;
		texGen.description	= glu::getTextureTargetStr(target).toString() + ", initial values";

		group.push_back(texGen);
	}

	// compressed
	if (isCompressionSupportedForTarget(target))
	{
		TextureGenerationSpec					texGen;
		TextureGenerationSpec::TextureLevelSpec	level;

		texGen.bindTarget		= target;
		texGen.queryTarget		= queryTarget;
		texGen.immutable		= false;
		texGen.description		= glu::getTextureTargetStr(target).toString() + ", compressed";

		level.width				= 32;
		level.height			= 32;
		level.depth				= (target == GL_TEXTURE_2D_ARRAY) ? (2) : (1);
		level.level				= 0;
		level.internalFormat	= GL_COMPRESSED_RGB8_ETC2;
		level.compressed		= true;

		texGen.levels.push_back(level);
		group.push_back(texGen);
	}
}

static void generateTextureBufferGenerationGroup (std::vector<TextureGenerationSpec>& group, glw::GLenum target)
{
	const glw::GLenum queryTarget = (target == GL_TEXTURE_CUBE_MAP) ? (GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) : (target);

	// initial
	{
		TextureGenerationSpec texGen;
		texGen.bindTarget		= target;
		texGen.queryTarget		= queryTarget;
		texGen.immutable		= true;
		texGen.sampleCount		= 0;
		texGen.description		= glu::getTextureTargetStr(target).toString() + ", initial values";

		group.push_back(texGen);
	}

	// actual specification tests are in texture_buffer tests, no need to do them here too
}

bool applyTextureGenerationSpec (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec, glw::GLuint& texBuffer)
{
	bool allOk = true;

	DE_ASSERT(!(spec.immutable && spec.levels.size() > 1));		// !< immutable textures have only one level

	for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
	{
		const glu::TransferFormat transferFormat = (spec.levels[levelNdx].compressed) ? (glu::TransferFormat()) : (glu::getTransferFormat(glu::mapGLInternalFormat(spec.levels[levelNdx].internalFormat)));

		if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D)
			gl.glTexStorage2D(spec.bindTarget, 1, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height);
		else if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_3D)
			gl.glTexStorage3D(spec.bindTarget, 1, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth);
		else if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D_ARRAY)
			gl.glTexStorage3D(spec.bindTarget, 1, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth);
		else if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_CUBE_MAP)
			gl.glTexStorage2D(spec.bindTarget, 1, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height);
		else if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D_MULTISAMPLE)
			gl.glTexStorage2DMultisample(spec.bindTarget, spec.sampleCount, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, (spec.fixedSamplePos) ? (GL_TRUE) : (GL_FALSE));
		else if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
			gl.glTexStorage3DMultisample(spec.bindTarget, spec.sampleCount, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth, (spec.fixedSamplePos) ? (GL_TRUE) : (GL_FALSE));
		else if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_CUBE_MAP_ARRAY)
			gl.glTexStorage3D(spec.bindTarget, 1, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth);
		else if (!spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D)
			gl.glTexImage2D(spec.bindTarget, spec.levels[levelNdx].level, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, 0, transferFormat.format, transferFormat.dataType, DE_NULL);
		else if (!spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_3D)
			gl.glTexImage3D(spec.bindTarget, spec.levels[levelNdx].level, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth, 0, transferFormat.format, transferFormat.dataType, DE_NULL);
		else if (!spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D_ARRAY)
			gl.glTexImage3D(spec.bindTarget, spec.levels[levelNdx].level, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth, 0, transferFormat.format, transferFormat.dataType, DE_NULL);
		else if (!spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_CUBE_MAP)
			gl.glTexImage2D(spec.queryTarget, spec.levels[levelNdx].level, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, 0, transferFormat.format, transferFormat.dataType, DE_NULL);
		else if (!spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_CUBE_MAP_ARRAY)
			gl.glTexImage3D(spec.bindTarget, spec.levels[levelNdx].level, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth, 0, transferFormat.format, transferFormat.dataType, DE_NULL);
		else if (!spec.immutable && spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D)
		{
			DE_ASSERT(spec.levels[levelNdx].width == 32);
			DE_ASSERT(spec.levels[levelNdx].height == 32);
			DE_ASSERT(spec.levels[levelNdx].internalFormat == GL_COMPRESSED_RGB8_ETC2);

			static const deUint8 buffer[64 * 8] = { 0 };
			gl.glCompressedTexImage2D(spec.bindTarget, spec.levels[levelNdx].level, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, 0, sizeof(buffer), buffer);
		}
		else if (!spec.immutable && spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D_ARRAY)
		{
			DE_ASSERT(spec.levels[levelNdx].width == 32);
			DE_ASSERT(spec.levels[levelNdx].height == 32);
			DE_ASSERT(spec.levels[levelNdx].depth == 2);
			DE_ASSERT(spec.levels[levelNdx].internalFormat == GL_COMPRESSED_RGB8_ETC2);

			static const deUint8 buffer[64 * 8 * 2] = { 0 };
			gl.glCompressedTexImage3D(spec.bindTarget, spec.levels[levelNdx].level, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth, 0, sizeof(buffer), buffer);
		}
		else if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_BUFFER)
		{
			gl.glGenBuffers(1, &texBuffer);
			gl.glBindBuffer(GL_TEXTURE_BUFFER, texBuffer);

			if (spec.bindWholeArray)
			{
				gl.glBufferData(GL_TEXTURE_BUFFER, spec.texBufferDataSize, DE_NULL, GL_STATIC_DRAW);
				gl.glTexBuffer(GL_TEXTURE_BUFFER, spec.levels[levelNdx].internalFormat, texBuffer);
			}
			else
			{
				gl.glBufferData(GL_TEXTURE_BUFFER, spec.texBufferDataOffset + spec.texBufferDataSize, DE_NULL, GL_STATIC_DRAW);
				gl.glTexBufferRange(GL_TEXTURE_BUFFER, spec.levels[levelNdx].internalFormat, texBuffer, spec.texBufferDataOffset, spec.texBufferDataSize);
			}
		}
		else
			DE_ASSERT(DE_FALSE);

		{
			const glw::GLenum err = gl.glGetError();
			if (err != GL_NO_ERROR)
			{
				gl.getLog()	<< tcu::TestLog::Message
							<< "Texture specification failed, got " + glu::getErrorStr(err).toString()
							<< tcu::TestLog::EndMessage;
				allOk = false;
			}
		}
	}

	return allOk;
}

class TextureLevelCase : public TestCase
{
public:
										TextureLevelCase		(Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type);
										~TextureLevelCase		(void);

	void								init					(void);
	void								deinit					(void);
	IterateResult						iterate					(void);

protected:
	void								getFormatSamples		(glw::GLenum internalFormat, std::vector<int>& samples);
	bool								testConfig				(const TextureGenerationSpec& spec);
	virtual bool						checkTextureState		(glu::CallLogWrapper& gl, const TextureGenerationSpec& spec) = 0;
	virtual void						generateTestIterations	(std::vector<TextureGenerationSpec>& iterations) = 0;

	const QueryType						m_type;
	const glw::GLenum					m_target;
	glw::GLuint							m_texture;
	glw::GLuint							m_texBuffer;

private:
	int									m_iteration;
	std::vector<TextureGenerationSpec>	m_iterations;
	bool								m_allIterationsOk;
	std::vector<int>					m_failedIterations;
};

TextureLevelCase::TextureLevelCase (Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type)
	: TestCase			(ctx, name, desc)
	, m_type			(type)
	, m_target			(target)
	, m_texture			(0)
	, m_texBuffer		(0)
	, m_iteration		(0)
	, m_allIterationsOk	(true)
{
}

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

void TextureLevelCase::init (void)
{
	if (!isCoreTextureTarget(m_target))
	{
		const char* const targetExtension = getTextureTargetExtension(m_target);

		if (!m_context.getContextInfo().isExtensionSupported(targetExtension))
			throw tcu::NotSupportedError("Test requires " + std::string(targetExtension) + " extension");
	}

	generateTestIterations(m_iterations);

	for (int iterationNdx = 0; iterationNdx < (int)m_iterations.size(); ++iterationNdx)
		DE_ASSERT(m_iterations[iterationNdx].bindTarget == m_target);
}

void TextureLevelCase::deinit (void)
{
	if (m_texture)
	{
		m_context.getRenderContext().getFunctions().deleteTextures(1, &m_texture);
		m_texture = 0;
	}
	if (m_texBuffer)
	{
		m_context.getRenderContext().getFunctions().deleteTextures(1, &m_texBuffer);
		m_texBuffer = 0;
	}
}

void TextureLevelCase::getFormatSamples (glw::GLenum internalFormat, std::vector<int>& samples)
{
	const glw::Functions	gl			= m_context.getRenderContext().getFunctions();
	int						sampleCount	= -1;

	if (!isMultisampleTarget(m_target))
		return;

	gl.getInternalformativ(m_target, internalFormat, GL_NUM_SAMPLE_COUNTS, 1, &sampleCount);

	if (sampleCount < 0)
		throw tcu::TestError("internal format query failed");

	samples.resize(sampleCount);

	if (sampleCount > 0)
	{
		gl.getInternalformativ(m_target, internalFormat, GL_SAMPLES, sampleCount, &samples[0]);
		GLU_EXPECT_NO_ERROR(gl.getError(), "get max samples");
	}
}

TextureLevelCase::IterateResult TextureLevelCase::iterate (void)
{
	const bool result = testConfig(m_iterations[m_iteration]);

	if (!result)
	{
		m_failedIterations.push_back(m_iteration);
		m_allIterationsOk = false;
	}

	if (++m_iteration < (int)m_iterations.size())
		return CONTINUE;

	if (m_allIterationsOk)
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
	else
	{
		tcu::MessageBuilder msg(&m_testCtx.getLog());

		msg << "Following iteration(s) failed: ";
		for (int ndx = 0; ndx < (int)m_failedIterations.size(); ++ndx)
		{
			if (ndx)
				msg << ", ";
			msg << (m_failedIterations[ndx] + 1);
		}
		msg << tcu::TestLog::EndMessage;

		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "One or more iterations failed");
	}
	return STOP;
}

bool TextureLevelCase::testConfig (const TextureGenerationSpec& spec)
{
	const tcu::ScopedLogSection section(m_testCtx.getLog(), "Iteration", std::string() + "Iteration " + de::toString(m_iteration+1) + "/" + de::toString((int)m_iterations.size()) + " - " + spec.description);
	glu::CallLogWrapper			gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
	bool						result;

	gl.enableLogging(true);

	gl.glGenTextures(1, &m_texture);
	gl.glBindTexture(spec.bindTarget, m_texture);
	GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen tex");

	// Set the state
	applyTextureGenerationSpec(gl, spec, m_texBuffer);

	// Verify the state
	result = checkTextureState(gl, spec);

	gl.glDeleteTextures(1, &m_texture);
	m_texture = 0;

	if (m_texBuffer)
	{
		gl.glDeleteBuffers(1, &m_texBuffer);
		m_texture = 0;
	}

	return result;
}

/*--------------------------------------------------------------------*//*!
 * \brief Test texture target
 *//*--------------------------------------------------------------------*/
class TextureLevelCommonCase : public TextureLevelCase
{
public:
						TextureLevelCommonCase	(Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type);

protected:
	virtual void		generateTestIterations	(std::vector<TextureGenerationSpec>& iterations);
};

TextureLevelCommonCase::TextureLevelCommonCase (Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type)
	: TextureLevelCase(ctx, name, desc, target, type)
{
}

void TextureLevelCommonCase::generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
{
	const glw::GLenum	internalFormat = GL_RGBA8;
	int					maxSamples;
	std::vector<int>	samples;

	getFormatSamples(internalFormat, samples);
	if (samples.empty())
		maxSamples = -1;
	else
		maxSamples = samples[0];

	generateColorTextureGenerationGroup(iterations, m_target, maxSamples, internalFormat);
}

class TextureLevelSampleCase : public TextureLevelCommonCase
{
public:
	TextureLevelSampleCase (Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type)
		: TextureLevelCommonCase(ctx, name, desc, target, type)
	{
	}

private:
	bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
	{
		const int queryLevel	= (spec.levels.empty()) ? (0) : (spec.levels[0].level);
		const int refValue		= (spec.levels.empty()) ? (0) : (spec.sampleCount);

		return verifyTextureLevelParameterGreaterOrEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_SAMPLES, refValue, m_type);
	}
};

class TextureLevelFixedSamplesCase : public TextureLevelCommonCase
{
public:
	TextureLevelFixedSamplesCase (Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type)
		: TextureLevelCommonCase(ctx, name, desc, target, type)
	{
	}

private:
	bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
	{
		const int queryLevel	= (spec.levels.empty()) ? (0) : (spec.levels[0].level);
		const int refValue		= (spec.levels.empty()) ? (1) : ((spec.fixedSamplePos) ? (1) : (0));

		return verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_FIXED_SAMPLE_LOCATIONS, refValue, m_type);
	}
};

class TextureLevelWidthCase : public TextureLevelCommonCase
{
public:
	TextureLevelWidthCase (Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type)
		: TextureLevelCommonCase(ctx, name, desc, target, type)
	{
	}

private:
	bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
	{
		const int	initialValue	= 0;
		bool		allOk			= true;

		if (spec.levels.empty())
		{
			const int queryLevel	= 0;
			const int refValue		= initialValue;

			allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_WIDTH, refValue, m_type);
		}
		else
		{
			for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
			{
				const int queryLevel	= spec.levels[levelNdx].level;
				const int refValue		= spec.levels[levelNdx].width;

				allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_WIDTH, refValue, m_type);
			}
		}

		return allOk;
	}
};

class TextureLevelHeightCase : public TextureLevelCommonCase
{
public:
	TextureLevelHeightCase (Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type)
		: TextureLevelCommonCase(ctx, name, desc, target, type)
	{
	}

private:
	bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
	{
		const int	initialValue	= 0;
		bool		allOk			= true;

		if (spec.levels.empty())
		{
			const int queryLevel	= 0;
			const int refValue		= initialValue;

			allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_HEIGHT, refValue, m_type);
		}
		else
		{
			for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
			{
				const int queryLevel	= spec.levels[levelNdx].level;
				const int refValue		= spec.levels[levelNdx].height;

				allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_HEIGHT, refValue, m_type);
			}
		}

		return allOk;
	}
};

class TextureLevelDepthCase : public TextureLevelCommonCase
{
public:
	TextureLevelDepthCase (Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type)
		: TextureLevelCommonCase(ctx, name, desc, target, type)
	{
	}

private:

	bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
	{
		const int	initialValue	= 0;
		bool		allOk			= true;

		if (spec.levels.empty())
		{
			const int queryLevel	= 0;
			const int refValue		= initialValue;

			allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_DEPTH, refValue, m_type);
		}
		else
		{
			for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
			{
				const int queryLevel	= spec.levels[levelNdx].level;
				const int refValue		= spec.levels[levelNdx].depth;

				allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_DEPTH, refValue, m_type);
			}
		}

		return allOk;
	}
};

class TextureLevelInternalFormatCase : public TextureLevelCase
{
public:
	TextureLevelInternalFormatCase (Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type)
		: TextureLevelCase(ctx, name, desc, target, type)
	{
	}

private:
	void generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
	{
		generateInternalFormatTextureGenerationGroup(iterations, m_target);
	}

	bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
	{
		bool allOk = true;

		if (spec.levels.empty())
		{
			const int queryLevel		= 0;
			const int initialValues[2]	= { GL_RGBA, GL_R8 };

			allOk &= verifyTextureLevelParameterInternalFormatAnyOf(gl, spec.queryTarget, queryLevel, GL_TEXTURE_INTERNAL_FORMAT, initialValues, DE_LENGTH_OF_ARRAY(initialValues), m_type);
		}
		else
		{
			for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
			{
				const int queryLevel	= spec.levels[levelNdx].level;
				const int refValue		= spec.levels[levelNdx].internalFormat;

				allOk &= verifyTextureLevelParameterInternalFormatEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_INTERNAL_FORMAT, refValue, m_type);
			}
		}

		return allOk;
	}
};

class TextureLevelSizeCase : public TextureLevelCase
{
public:
						TextureLevelSizeCase			(Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type, glw::GLenum pname);

private:
	void				generateTestIterations			(std::vector<TextureGenerationSpec>& iterations);
	bool				checkTextureState				(glu::CallLogWrapper& gl, const TextureGenerationSpec& spec);
	int					getMinimumComponentResolution	(glw::GLenum internalFormat);

	const glw::GLenum	m_pname;
};

TextureLevelSizeCase::TextureLevelSizeCase (Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type, glw::GLenum pname)
	: TextureLevelCase	(ctx, name, desc, target, type)
	, m_pname			(pname)
{
}

void TextureLevelSizeCase::generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
{
	generateInternalFormatTextureGenerationGroup(iterations, m_target);
}

bool TextureLevelSizeCase::checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
{
	bool allOk = true;

	if (spec.levels.empty())
	{
		allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, 0, m_pname, 0, m_type);
	}
	else
	{
		for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
		{
			const int queryLevel	= spec.levels[levelNdx].level;
			const int refValue		= getMinimumComponentResolution(spec.levels[levelNdx].internalFormat);

			allOk &= verifyTextureLevelParameterGreaterOrEqual(gl, spec.queryTarget, queryLevel, m_pname, refValue, m_type);
		}
	}

	return allOk;
}

int TextureLevelSizeCase::getMinimumComponentResolution (glw::GLenum internalFormat)
{
	const tcu::TextureFormat	format			= glu::mapGLInternalFormat(internalFormat);
	const tcu::IVec4			channelBitDepth	= tcu::getTextureFormatBitDepth(format);

	switch (m_pname)
	{
		case GL_TEXTURE_RED_SIZE:
			if (format.order == tcu::TextureFormat::R		||
				format.order == tcu::TextureFormat::RG		||
				format.order == tcu::TextureFormat::RGB		||
				format.order == tcu::TextureFormat::RGBA	||
				format.order == tcu::TextureFormat::BGRA	||
				format.order == tcu::TextureFormat::ARGB	||
				format.order == tcu::TextureFormat::sRGB	||
				format.order == tcu::TextureFormat::sRGBA)
				return channelBitDepth[0];
			else
				return 0;

		case GL_TEXTURE_GREEN_SIZE:
			if (format.order == tcu::TextureFormat::RG		||
				format.order == tcu::TextureFormat::RGB		||
				format.order == tcu::TextureFormat::RGBA	||
				format.order == tcu::TextureFormat::BGRA	||
				format.order == tcu::TextureFormat::ARGB	||
				format.order == tcu::TextureFormat::sRGB	||
				format.order == tcu::TextureFormat::sRGBA)
				return channelBitDepth[1];
			else
				return 0;

		case GL_TEXTURE_BLUE_SIZE:
			if (format.order == tcu::TextureFormat::RGB		||
				format.order == tcu::TextureFormat::RGBA	||
				format.order == tcu::TextureFormat::BGRA	||
				format.order == tcu::TextureFormat::ARGB	||
				format.order == tcu::TextureFormat::sRGB	||
				format.order == tcu::TextureFormat::sRGBA)
				return channelBitDepth[2];
			else
				return 0;

		case GL_TEXTURE_ALPHA_SIZE:
			if (format.order == tcu::TextureFormat::RGBA	||
				format.order == tcu::TextureFormat::BGRA	||
				format.order == tcu::TextureFormat::ARGB	||
				format.order == tcu::TextureFormat::sRGBA)
				return channelBitDepth[3];
			else
				return 0;

		case GL_TEXTURE_DEPTH_SIZE:
			if (format.order == tcu::TextureFormat::D	||
				format.order == tcu::TextureFormat::DS)
				return channelBitDepth[0];
			else
				return 0;

		case GL_TEXTURE_STENCIL_SIZE:
			if (format.order == tcu::TextureFormat::DS)
				return channelBitDepth[3];
			else
				return 0;

		case GL_TEXTURE_SHARED_SIZE:
			if (internalFormat == GL_RGB9_E5)
				return 5;
			else
				return 0;
		default:
			DE_ASSERT(DE_FALSE);
			return 0;
	}
}

class TextureLevelTypeCase : public TextureLevelCase
{
public:
						TextureLevelTypeCase			(Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type, glw::GLenum pname);

private:
	void				generateTestIterations			(std::vector<TextureGenerationSpec>& iterations);
	bool				checkTextureState				(glu::CallLogWrapper& gl, const TextureGenerationSpec& spec);
	int					getComponentType				(glw::GLenum internalFormat);

	const glw::GLenum	m_pname;
};

TextureLevelTypeCase::TextureLevelTypeCase (Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type, glw::GLenum pname)
	: TextureLevelCase	(ctx, name, desc, target, type)
	, m_pname			(pname)
{
}

void TextureLevelTypeCase::generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
{
	generateInternalFormatTextureGenerationGroup(iterations, m_target);
}

bool TextureLevelTypeCase::checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
{
	bool allOk = true;

	if (spec.levels.empty())
	{
		allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, 0, m_pname, GL_NONE, m_type);
	}
	else
	{
		for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
		{
			const int queryLevel	= spec.levels[levelNdx].level;
			const int refValue		= getComponentType(spec.levels[levelNdx].internalFormat);

			allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, m_pname, refValue, m_type);
		}
	}

	return allOk;
}

int TextureLevelTypeCase::getComponentType (glw::GLenum internalFormat)
{
	const tcu::TextureFormat		format			= glu::mapGLInternalFormat(internalFormat);
	const tcu::TextureChannelClass	channelClass	= tcu::getTextureChannelClass(format.type);
	glw::GLenum						channelType		= GL_NONE;

	// depth-stencil special cases
	if (format.type == tcu::TextureFormat::UNSIGNED_INT_24_8)
	{
		if (m_pname == GL_TEXTURE_DEPTH_TYPE)
			return GL_UNSIGNED_NORMALIZED;
		else
			return GL_NONE;
	}
	else if (format.type == tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV)
	{
		if (m_pname == GL_TEXTURE_DEPTH_TYPE)
			return GL_FLOAT;
		else
			return GL_NONE;
	}
	else
	{
		switch (channelClass)
		{
			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:		channelType = GL_SIGNED_NORMALIZED;		break;
			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:		channelType = GL_UNSIGNED_NORMALIZED;	break;
			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:			channelType = GL_INT;					break;
			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:			channelType = GL_UNSIGNED_INT;			break;
			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:			channelType = GL_FLOAT;					break;
			default:
				DE_ASSERT(DE_FALSE);
		}
	}

	switch (m_pname)
	{
		case GL_TEXTURE_RED_TYPE:
			if (format.order == tcu::TextureFormat::R		||
				format.order == tcu::TextureFormat::RG		||
				format.order == tcu::TextureFormat::RGB		||
				format.order == tcu::TextureFormat::RGBA	||
				format.order == tcu::TextureFormat::BGRA	||
				format.order == tcu::TextureFormat::ARGB	||
				format.order == tcu::TextureFormat::sRGB	||
				format.order == tcu::TextureFormat::sRGBA)
				return channelType;
			else
				return GL_NONE;

		case GL_TEXTURE_GREEN_TYPE:
			if (format.order == tcu::TextureFormat::RG		||
				format.order == tcu::TextureFormat::RGB		||
				format.order == tcu::TextureFormat::RGBA	||
				format.order == tcu::TextureFormat::BGRA	||
				format.order == tcu::TextureFormat::ARGB	||
				format.order == tcu::TextureFormat::sRGB	||
				format.order == tcu::TextureFormat::sRGBA)
				return channelType;
			else
				return GL_NONE;

		case GL_TEXTURE_BLUE_TYPE:
			if (format.order == tcu::TextureFormat::RGB		||
				format.order == tcu::TextureFormat::RGBA	||
				format.order == tcu::TextureFormat::BGRA	||
				format.order == tcu::TextureFormat::ARGB	||
				format.order == tcu::TextureFormat::sRGB	||
				format.order == tcu::TextureFormat::sRGBA)
				return channelType;
			else
				return GL_NONE;

		case GL_TEXTURE_ALPHA_TYPE:
			if (format.order == tcu::TextureFormat::RGBA	||
				format.order == tcu::TextureFormat::BGRA	||
				format.order == tcu::TextureFormat::ARGB	||
				format.order == tcu::TextureFormat::sRGBA)
				return channelType;
			else
				return GL_NONE;

		case GL_TEXTURE_DEPTH_TYPE:
			if (format.order == tcu::TextureFormat::D	||
				format.order == tcu::TextureFormat::DS)
				return channelType;
			else
				return GL_NONE;

		default:
			DE_ASSERT(DE_FALSE);
			return 0;
	}
}

class TextureLevelCompressedCase : public TextureLevelCase
{
public:
	TextureLevelCompressedCase (Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type)
		: TextureLevelCase(ctx, name, desc, target, type)
	{
	}

private:
	void generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
	{
		generateCompressedTextureGenerationGroup(iterations, m_target);
	}

	bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
	{
		bool allOk = true;

		if (spec.levels.empty())
		{
			allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, 0, GL_TEXTURE_COMPRESSED, 0, m_type);
		}
		else
		{
			for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
			{
				const int queryLevel	= spec.levels[levelNdx].level;
				const int refValue		= (spec.levels[levelNdx].compressed) ? (1) : (0);

				allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_COMPRESSED, refValue, m_type);
			}
		}

		return allOk;
	}
};

class TextureLevelBufferDataStoreCase : public TextureLevelCase
{
public:
	TextureLevelBufferDataStoreCase (Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type)
		: TextureLevelCase(ctx, name, desc, target, type)
	{
	}

private:
	void init (void)
	{
		if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_buffer"))
			throw tcu::NotSupportedError("Test requires GL_EXT_texture_buffer extension");
		TextureLevelCase::init();
	}

	void generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
	{
		generateTextureBufferGenerationGroup(iterations, m_target);
	}

	bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
	{
		bool allOk = true;

		if (spec.levels.empty())
		{
			allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, 0, GL_TEXTURE_BUFFER_DATA_STORE_BINDING, 0, m_type);
		}
		else
		{
			allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, 0, GL_TEXTURE_BUFFER_DATA_STORE_BINDING, m_texBuffer, m_type);
		}

		return allOk;
	}
};

class TextureLevelBufferDataOffsetCase : public TextureLevelCase
{
public:
	TextureLevelBufferDataOffsetCase (Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type)
		: TextureLevelCase(ctx, name, desc, target, type)
	{
	}

private:
	void init (void)
	{
		if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_buffer"))
			throw tcu::NotSupportedError("Test requires GL_EXT_texture_buffer extension");
		TextureLevelCase::init();
	}

	void generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
	{
		generateTextureBufferGenerationGroup(iterations, m_target);
	}

	bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
	{
		bool allOk = true;

		if (spec.levels.empty())
		{
			allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, 0, GL_TEXTURE_BUFFER_OFFSET, 0, m_type);
		}
		else
		{
			const int refValue = spec.texBufferDataOffset;

			allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, 0, GL_TEXTURE_BUFFER_OFFSET, refValue, m_type);
		}

		return allOk;
	}
};

class TextureLevelBufferDataSizeCase : public TextureLevelCase
{
public:
	TextureLevelBufferDataSizeCase (Context& ctx, const char* name, const char* desc, glw::GLenum target, QueryType type)
		: TextureLevelCase(ctx, name, desc, target, type)
	{
	}

private:
	void init (void)
	{
		if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_buffer"))
			throw tcu::NotSupportedError("Test requires GL_EXT_texture_buffer extension");
		TextureLevelCase::init();
	}

	void generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
	{
		generateTextureBufferGenerationGroup(iterations, m_target);
	}

	bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
	{
		bool allOk = true;

		if (spec.levels.empty())
		{
			allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, 0, GL_TEXTURE_BUFFER_SIZE, 0, m_type);
		}
		else
		{
			const int refValue = spec.texBufferDataSize;

			allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, 0, GL_TEXTURE_BUFFER_SIZE, refValue, m_type);
		}

		return allOk;
	}
};

} // anonymous

static const char* getVerifierSuffix (QueryType type)
{
	switch (type)
	{
		case QUERY_TEXTURE_LEVEL_FLOAT:		return "_float";
		case QUERY_TEXTURE_LEVEL_INTEGER:	return "_integer";
		default:
			DE_ASSERT(DE_FALSE);
			return DE_NULL;
	}
}

TextureLevelStateQueryTests::TextureLevelStateQueryTests (Context& context)
	: TestCaseGroup(context, "texture_level", "GetTexLevelParameter tests")
{
}

TextureLevelStateQueryTests::~TextureLevelStateQueryTests (void)
{
}

void TextureLevelStateQueryTests::init (void)
{
	static const QueryType verifiers[] =
	{
		QUERY_TEXTURE_LEVEL_INTEGER,
		QUERY_TEXTURE_LEVEL_FLOAT,
	};

#define FOR_EACH_VERIFIER(X) \
	for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(verifiers); ++verifierNdx)	\
	{																						\
		const std::string verifierSuffix = getVerifierSuffix(verifiers[verifierNdx]);		\
		const QueryType verifier = verifiers[verifierNdx];									\
		targetGroup->addChild(X);															\
	}
	static const struct
	{
		const char*	name;
		glw::GLenum	target;
	} textureTargets[] =
	{
		{ "texture_2d",						GL_TEXTURE_2D,						},
		{ "texture_3d",						GL_TEXTURE_3D,						},
		{ "texture_2d_array",				GL_TEXTURE_2D_ARRAY,				},
		{ "texture_cube_map",				GL_TEXTURE_CUBE_MAP,				},
		{ "texture_2d_multisample",			GL_TEXTURE_2D_MULTISAMPLE,			},
		{ "texture_2d_multisample_array",	GL_TEXTURE_2D_MULTISAMPLE_ARRAY,	}, // GL_OES_texture_storage_multisample_2d_array
		{ "texture_buffer",					GL_TEXTURE_BUFFER,					}, // GL_EXT_texture_buffer
		{ "texture_cube_array",				GL_TEXTURE_CUBE_MAP_ARRAY,			}, // GL_EXT_texture_cube_map_array
	};

	for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(textureTargets); ++targetNdx)
	{
		tcu::TestCaseGroup* const targetGroup = new tcu::TestCaseGroup(m_testCtx, textureTargets[targetNdx].name, textureTargets[targetNdx].name);
		addChild(targetGroup);

		FOR_EACH_VERIFIER(new TextureLevelSampleCase			(m_context, ("samples" + verifierSuffix).c_str(),					"Verify TEXTURE_SAMPLES",					textureTargets[targetNdx].target,	verifier));
		FOR_EACH_VERIFIER(new TextureLevelFixedSamplesCase		(m_context, ("fixed_sample_locations" + verifierSuffix).c_str(),	"Verify TEXTURE_FIXED_SAMPLE_LOCATIONS",	textureTargets[targetNdx].target,	verifier));
		FOR_EACH_VERIFIER(new TextureLevelWidthCase				(m_context, ("width" + verifierSuffix).c_str(),						"Verify TEXTURE_WIDTH",						textureTargets[targetNdx].target,	verifier));
		FOR_EACH_VERIFIER(new TextureLevelHeightCase			(m_context, ("height" + verifierSuffix).c_str(),					"Verify TEXTURE_HEIGHT",					textureTargets[targetNdx].target,	verifier));
		FOR_EACH_VERIFIER(new TextureLevelDepthCase				(m_context, ("depth" + verifierSuffix).c_str(),						"Verify TEXTURE_DEPTH",						textureTargets[targetNdx].target,	verifier));
		FOR_EACH_VERIFIER(new TextureLevelInternalFormatCase	(m_context, ("internal_format" + verifierSuffix).c_str(),			"Verify TEXTURE_INTERNAL_FORMAT",			textureTargets[targetNdx].target,	verifier));
		FOR_EACH_VERIFIER(new TextureLevelSizeCase				(m_context, ("red_size" + verifierSuffix).c_str(),					"Verify TEXTURE_RED_SIZE",					textureTargets[targetNdx].target,	verifier,	GL_TEXTURE_RED_SIZE));
		FOR_EACH_VERIFIER(new TextureLevelSizeCase				(m_context, ("green_size" + verifierSuffix).c_str(),				"Verify TEXTURE_GREEN_SIZE",				textureTargets[targetNdx].target,	verifier,	GL_TEXTURE_GREEN_SIZE));
		FOR_EACH_VERIFIER(new TextureLevelSizeCase				(m_context, ("blue_size" + verifierSuffix).c_str(),					"Verify TEXTURE_BLUE_SIZE",					textureTargets[targetNdx].target,	verifier,	GL_TEXTURE_BLUE_SIZE));
		FOR_EACH_VERIFIER(new TextureLevelSizeCase				(m_context, ("alpha_size" + verifierSuffix).c_str(),				"Verify TEXTURE_ALPHA_SIZE",				textureTargets[targetNdx].target,	verifier,	GL_TEXTURE_ALPHA_SIZE));
		FOR_EACH_VERIFIER(new TextureLevelSizeCase				(m_context, ("depth_size" + verifierSuffix).c_str(),				"Verify TEXTURE_DEPTH_SIZE",				textureTargets[targetNdx].target,	verifier,	GL_TEXTURE_DEPTH_SIZE));
		FOR_EACH_VERIFIER(new TextureLevelSizeCase				(m_context, ("stencil_size" + verifierSuffix).c_str(),				"Verify TEXTURE_STENCIL_SIZE",				textureTargets[targetNdx].target,	verifier,	GL_TEXTURE_STENCIL_SIZE));
		FOR_EACH_VERIFIER(new TextureLevelSizeCase				(m_context, ("shared_size" + verifierSuffix).c_str(),				"Verify TEXTURE_SHARED_SIZE",				textureTargets[targetNdx].target,	verifier,	GL_TEXTURE_SHARED_SIZE));
		FOR_EACH_VERIFIER(new TextureLevelTypeCase				(m_context, ("red_type" + verifierSuffix).c_str(),					"Verify TEXTURE_RED_TYPE",					textureTargets[targetNdx].target,	verifier,	GL_TEXTURE_RED_TYPE));
		FOR_EACH_VERIFIER(new TextureLevelTypeCase				(m_context, ("green_type" + verifierSuffix).c_str(),				"Verify TEXTURE_GREEN_TYPE",				textureTargets[targetNdx].target,	verifier,	GL_TEXTURE_GREEN_TYPE));
		FOR_EACH_VERIFIER(new TextureLevelTypeCase				(m_context, ("blue_type" + verifierSuffix).c_str(),					"Verify TEXTURE_BLUE_TYPE",					textureTargets[targetNdx].target,	verifier,	GL_TEXTURE_BLUE_TYPE));
		FOR_EACH_VERIFIER(new TextureLevelTypeCase				(m_context, ("alpha_type" + verifierSuffix).c_str(),				"Verify TEXTURE_ALPHA_TYPE",				textureTargets[targetNdx].target,	verifier,	GL_TEXTURE_ALPHA_TYPE));
		FOR_EACH_VERIFIER(new TextureLevelTypeCase				(m_context, ("depth_type" + verifierSuffix).c_str(),				"Verify TEXTURE_DEPTH_TYPE",				textureTargets[targetNdx].target,	verifier,	GL_TEXTURE_DEPTH_TYPE));
		FOR_EACH_VERIFIER(new TextureLevelCompressedCase		(m_context, ("compressed" + verifierSuffix).c_str(),				"Verify TEXTURE_COMPRESSED",				textureTargets[targetNdx].target,	verifier));
		FOR_EACH_VERIFIER(new TextureLevelBufferDataStoreCase	(m_context, ("buffer_data_store_binding" + verifierSuffix).c_str(),	"Verify TEXTURE_BUFFER_DATA_STORE_BINDING",	textureTargets[targetNdx].target,	verifier));
		FOR_EACH_VERIFIER(new TextureLevelBufferDataOffsetCase	(m_context, ("buffer_offset" + verifierSuffix).c_str(),				"Verify TEXTURE_BUFFER_OFFSET",				textureTargets[targetNdx].target,	verifier));
		FOR_EACH_VERIFIER(new TextureLevelBufferDataSizeCase	(m_context, ("buffer_size" + verifierSuffix).c_str(),				"Verify TEXTURE_BUFFER_SIZE",				textureTargets[targetNdx].target,	verifier));
	}

#undef FOR_EACH_VERIFIER
}

} // Functional
} // gles31
} // deqp
