/*-------------------------------------------------------------------------
 * 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 format tests.
 *//*--------------------------------------------------------------------*/

#include "es31fTextureFormatTests.hpp"
#include "gluContextInfo.hpp"
#include "gluPixelTransfer.hpp"
#include "gluStrUtil.hpp"
#include "gluTexture.hpp"
#include "gluTextureUtil.hpp"
#include "glsTextureTestUtil.hpp"
#include "tcuTextureUtil.hpp"
#include "deStringUtil.hpp"
#include "deRandom.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"

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

namespace deqp
{
namespace gles31
{
namespace Functional
{

using namespace deqp::gls;
using namespace deqp::gls::TextureTestUtil;
using namespace glu::TextureTestUtil;

using tcu::Sampler;

static tcu::CubeFace getCubeFaceFromNdx (int ndx)
{
	switch (ndx)
	{
		case 0:	return tcu::CUBEFACE_POSITIVE_X;
		case 1:	return tcu::CUBEFACE_NEGATIVE_X;
		case 2:	return tcu::CUBEFACE_POSITIVE_Y;
		case 3:	return tcu::CUBEFACE_NEGATIVE_Y;
		case 4:	return tcu::CUBEFACE_POSITIVE_Z;
		case 5:	return tcu::CUBEFACE_NEGATIVE_Z;
		default:
			DE_ASSERT(false);
			return tcu::CUBEFACE_LAST;
	}
}

// TextureCubeArrayFormatCase

class TextureCubeArrayFormatCase : public tcu::TestCase
{
public:
										TextureCubeArrayFormatCase	(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& renderCtxInfo, const char* name, const char* description, deUint32 format, deUint32 dataType, int size, int depth);
										TextureCubeArrayFormatCase	(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& renderCtxInfo, const char* name, const char* description, deUint32 internalFormat, int size, int depth);
										~TextureCubeArrayFormatCase	(void);

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

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

	bool								checkSupport				(void);
	bool								testLayerFace				(int layerNdx);

	glu::RenderContext&					m_renderCtx;
	const glu::ContextInfo&				m_renderCtxInfo;

	const deUint32						m_format;
	const deUint32						m_dataType;
	const int							m_size;
	const int							m_depth;

	glu::TextureCubeArray*				m_texture;
	TextureTestUtil::TextureRenderer	m_renderer;

	int									m_curLayerFace;
};

TextureCubeArrayFormatCase::TextureCubeArrayFormatCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& renderCtxInfo, const char* name, const char* description, deUint32 format, deUint32 dataType, int size, int depth)
	: TestCase			(testCtx, name, description)
	, m_renderCtx		(renderCtx)
	, m_renderCtxInfo	(renderCtxInfo)
	, m_format			(format)
	, m_dataType		(dataType)
	, m_size			(size)
	, m_depth			(depth)
	, m_texture			(DE_NULL)
	, m_renderer		(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_310_ES, glu::PRECISION_HIGHP)
	, m_curLayerFace	(0)
{
}

TextureCubeArrayFormatCase::TextureCubeArrayFormatCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& renderCtxInfo, const char* name, const char* description, deUint32 internalFormat, int size, int depth)
	: TestCase			(testCtx, name, description)
	, m_renderCtx		(renderCtx)
	, m_renderCtxInfo	(renderCtxInfo)
	, m_format			(internalFormat)
	, m_dataType		(GL_NONE)
	, m_size			(size)
	, m_depth			(depth)
	, m_texture			(DE_NULL)
	, m_renderer		(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_310_ES, glu::PRECISION_HIGHP)
	, m_curLayerFace	(0)
{
}

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

void TextureCubeArrayFormatCase::init (void)
{
	if (checkSupport())
	{
		m_texture = m_dataType != GL_NONE
				  ? new glu::TextureCubeArray(m_renderCtx, m_format, m_dataType, m_size, m_depth)	// Implicit internal format.
				  : new glu::TextureCubeArray(m_renderCtx, m_format, m_size, m_depth);				// Explicit internal format.

		tcu::TextureFormatInfo spec = tcu::getTextureFormatInfo(m_texture->getRefTexture().getFormat());

		// Fill level 0.
		m_texture->getRefTexture().allocLevel(0);
		tcu::fillWithComponentGradients(m_texture->getRefTexture().getLevel(0), spec.valueMin, spec.valueMax);

		// Initialize state.
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
		m_curLayerFace = 0;
	}
	else
	{
		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Cube map arrays not supported");
	}
}

void TextureCubeArrayFormatCase::deinit (void)
{
	delete m_texture;
	m_texture = DE_NULL;

	m_renderer.clear();
}

bool TextureCubeArrayFormatCase::checkSupport (void)
{
	return m_renderCtxInfo.isExtensionSupported("GL_EXT_texture_cube_map_array");
}

bool TextureCubeArrayFormatCase::testLayerFace (int layerFaceNdx)
{
	const glw::Functions&	gl				= m_renderCtx.getFunctions();
	TestLog&				log				= m_testCtx.getLog();
	RandomViewport			viewport		(m_renderCtx.getRenderTarget(), m_size, m_size, deStringHash(getName()));
	tcu::Surface			renderedFrame	(viewport.width, viewport.height);
	tcu::Surface			referenceFrame	(viewport.width, viewport.height);
	tcu::RGBA				threshold		= m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
	vector<float>			texCoord;
	ReferenceParams			renderParams	(TEXTURETYPE_CUBE_ARRAY);
	tcu::TextureFormatInfo	spec			= tcu::getTextureFormatInfo(m_texture->getRefTexture().getFormat());
	const int				layerNdx		= layerFaceNdx / 6;
	const tcu::CubeFace		face			= getCubeFaceFromNdx(layerFaceNdx % 6);

	renderParams.samplerType				= getSamplerType(m_texture->getRefTexture().getFormat());
	renderParams.sampler					= Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST, Sampler::NEAREST);
	renderParams.sampler.seamlessCubeMap	= true;
	renderParams.colorScale					= spec.lookupScale;
	renderParams.colorBias					= spec.lookupBias;

	// Layer here specifies the cube slice
	computeQuadTexCoordCubeArray(texCoord, face, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f), tcu::Vec2((float)layerNdx));

	// Setup base viewport.
	gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);

	// Upload texture data to GL.
	m_texture->upload();

	// Bind to unit 0.
	gl.activeTexture(GL_TEXTURE0);
	gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_texture->getGLTexture());

	// Setup nearest neighbor filtering and clamp-to-edge.
	gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");

	// Draw.
	m_renderer.renderQuad(0, &texCoord[0], renderParams);
	glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());

	// Compute reference.
	sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat()), m_texture->getRefTexture(), &texCoord[0], renderParams);

	// Compare and log.
	return compareImages(log, (string("LayerFace" + de::toString(layerFaceNdx))).c_str(), (string("Layer-face " + de::toString(layerFaceNdx))).c_str(), referenceFrame, renderedFrame, threshold);
}

TextureCubeArrayFormatCase::IterateResult TextureCubeArrayFormatCase::iterate (void)
{
	if (m_testCtx.getTestResult() == QP_TEST_RESULT_NOT_SUPPORTED)
		return STOP;

	// Execute test for all layers.
	bool isOk = testLayerFace(m_curLayerFace);

	if (!isOk && m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");

	m_curLayerFace += 1;

	return m_curLayerFace < m_texture->getRefTexture().getDepth() ? CONTINUE : STOP;
}

// TextureBufferFormatCase

class TextureBufferFormatCase : public TestCase
{
public:
								TextureBufferFormatCase		(Context& ctx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 internalFormat, int width);
								~TextureBufferFormatCase	(void);

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

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

	glu::RenderContext&			m_renderCtx;

	deUint32					m_format;
	int							m_width;
	int							m_maxTextureBufferSize;

	glu::TextureBuffer*			m_texture;
	TextureRenderer				m_renderer;
};

TextureBufferFormatCase::TextureBufferFormatCase (Context& ctx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 internalFormat, int width)
	: TestCase					(ctx, name, description)
	, m_renderCtx				(renderCtx)
	, m_format					(internalFormat)
	, m_width					(width)
	, m_maxTextureBufferSize	(0)
	, m_texture					(DE_NULL)
	, m_renderer				(renderCtx, ctx.getTestContext().getLog(), glu::GLSL_VERSION_310_ES, glu::PRECISION_HIGHP)
{
}

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

void TextureBufferFormatCase::init (void)
{
	TestLog&				log		= m_testCtx.getLog();
	tcu::TextureFormat		fmt		= glu::mapGLInternalFormat(m_format);
	tcu::TextureFormatInfo	spec	= tcu::getTextureFormatInfo(fmt);
	tcu::Vec4				colorA	(spec.valueMin.x(), spec.valueMax.y(), spec.valueMin.z(), spec.valueMax.w());
	tcu::Vec4				colorB	(spec.valueMax.x(), spec.valueMin.y(), spec.valueMax.z(), spec.valueMin.w());

	if (!m_context.getContextInfo().isExtensionSupported("GL_OES_texture_buffer")
		&& !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_buffer"))
	{
		TCU_THROW(NotSupportedError, "Texture buffers not supported");
	}

	m_maxTextureBufferSize = m_context.getContextInfo().getInt(GL_MAX_TEXTURE_BUFFER_SIZE);

	if (m_maxTextureBufferSize <= 0)
		TCU_THROW(NotSupportedError, "GL_MAX_TEXTURE_BUFFER_SIZE > 0 required");

	log << TestLog::Message << "Buffer texture, " << glu::getTextureFormatStr(m_format) << ", " << m_width
							<< ",\n  fill with " << formatGradient(&colorA, &colorB) << " gradient"
		<< TestLog::EndMessage;

	m_texture = new glu::TextureBuffer(m_renderCtx, m_format, m_width * fmt.getPixelSize());

	// Fill level 0.
	tcu::fillWithComponentGradients(m_texture->getFullRefTexture(), colorA, colorB);
}

void TextureBufferFormatCase::deinit (void)
{
	delete m_texture;
	m_texture = DE_NULL;

	m_renderer.clear();
}

TextureBufferFormatCase::IterateResult TextureBufferFormatCase::iterate (void)
{
	TestLog&							log						= m_testCtx.getLog();
	const glw::Functions&				gl						= m_renderCtx.getFunctions();
	RandomViewport						viewport				(m_renderCtx.getRenderTarget(), m_width, 1, deStringHash(getName()));
	tcu::Surface						renderedFrame			(viewport.width, viewport.height);
	tcu::Surface						referenceFrame			(viewport.width, viewport.height);
	tcu::RGBA							threshold				= m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
	vector<float>						texCoord;
	RenderParams						renderParams			(TEXTURETYPE_BUFFER);
	const tcu::ConstPixelBufferAccess	effectiveRefTexture		= glu::getTextureBufferEffectiveRefTexture(*m_texture, m_maxTextureBufferSize);
	tcu::TextureFormatInfo				spec					= tcu::getTextureFormatInfo(effectiveRefTexture.getFormat());

	renderParams.flags			|= RenderParams::LOG_ALL;
	renderParams.samplerType	= getFetchSamplerType(effectiveRefTexture.getFormat());
	renderParams.colorScale		= spec.lookupScale;
	renderParams.colorBias		= spec.lookupBias;

	computeQuadTexCoord1D(texCoord, 0.0f, (float)(effectiveRefTexture.getWidth()));

	gl.clearColor(0.125f, 0.25f, 0.5f, 1.0f);
	gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

	// Setup base viewport.
	gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);

	// Upload texture data to GL.
	m_texture->upload();

	// Bind to unit 0.
	gl.activeTexture(GL_TEXTURE0);
	gl.bindTexture(GL_TEXTURE_BUFFER, m_texture->getGLTexture());

	GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");

	// Draw.
	m_renderer.renderQuad(0, &texCoord[0], renderParams);
	glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());

	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");

	// Compute reference.
	fetchTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat()), effectiveRefTexture, &texCoord[0], spec.lookupScale, spec.lookupBias);

	// Compare and log.
	bool isOk = compareImages(log, referenceFrame, renderedFrame, threshold);

	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
							isOk ? "Pass"				: "Image comparison failed");

	return STOP;
}

// TextureFormatTests

TextureFormatTests::TextureFormatTests (Context& context)
	: TestCaseGroup(context, "format", "Texture Format Tests")
{
}

TextureFormatTests::~TextureFormatTests (void)
{
}

vector<string> toStringVector (const char* const* str, int numStr)
{
	vector<string> v;
	v.resize(numStr);
	for (int i = 0; i < numStr; i++)
		v[i] = str[i];
	return v;
}

void TextureFormatTests::init (void)
{
	tcu::TestCaseGroup* unsizedGroup	= DE_NULL;
	tcu::TestCaseGroup*	sizedGroup		= DE_NULL;
	tcu::TestCaseGroup*	sizedBufferGroup = DE_NULL;
	addChild((unsizedGroup		= new tcu::TestCaseGroup(m_testCtx,	"unsized",	"Unsized formats")));
	addChild((sizedGroup		= new tcu::TestCaseGroup(m_testCtx,	"sized",	"Sized formats")));
	addChild((sizedBufferGroup	= new tcu::TestCaseGroup(m_testCtx,	"buffer",	"Sized formats (Buffer)")));

	tcu::TestCaseGroup*	sizedCubeArrayGroup	= DE_NULL;
	sizedGroup->addChild((sizedCubeArrayGroup = new tcu::TestCaseGroup(m_testCtx, "cube_array", "Sized formats (2D Array)")));

	struct
	{
		const char*	name;
		deUint32	format;
		deUint32	dataType;
	} texFormats[] =
	{
		{ "alpha",							GL_ALPHA,			GL_UNSIGNED_BYTE },
		{ "luminance",						GL_LUMINANCE,		GL_UNSIGNED_BYTE },
		{ "luminance_alpha",				GL_LUMINANCE_ALPHA,	GL_UNSIGNED_BYTE },
		{ "rgb_unsigned_short_5_6_5",		GL_RGB,				GL_UNSIGNED_SHORT_5_6_5 },
		{ "rgb_unsigned_byte",				GL_RGB,				GL_UNSIGNED_BYTE },
		{ "rgba_unsigned_short_4_4_4_4",	GL_RGBA,			GL_UNSIGNED_SHORT_4_4_4_4 },
		{ "rgba_unsigned_short_5_5_5_1",	GL_RGBA,			GL_UNSIGNED_SHORT_5_5_5_1 },
		{ "rgba_unsigned_byte",				GL_RGBA,			GL_UNSIGNED_BYTE }
	};

	for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(texFormats); formatNdx++)
	{
		deUint32	format		= texFormats[formatNdx].format;
		deUint32	dataType	= texFormats[formatNdx].dataType;
		string	nameBase		= texFormats[formatNdx].name;
		string	descriptionBase	= string(glu::getTextureFormatName(format)) + ", " + glu::getTypeName(dataType);

		unsizedGroup->addChild(new TextureCubeArrayFormatCase (m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), (nameBase + "_cube_array_pot").c_str(),		(descriptionBase + ", GL_TEXTURE_CUBE_MAP_ARRAY").c_str(), format, dataType, 64, 12));
		unsizedGroup->addChild(new TextureCubeArrayFormatCase (m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), (nameBase + "_cube_array_npot").c_str(),	(descriptionBase + ", GL_TEXTURE_CUBE_MAP_ARRAY").c_str(), format, dataType, 64, 12));
	}

	struct
	{
		const char*	name;
		deUint32	internalFormat;
	} sizedColorFormats[] =
	{
		{ "rgba32f",			GL_RGBA32F,			},
		{ "rgba32i",			GL_RGBA32I,			},
		{ "rgba32ui",			GL_RGBA32UI,		},
		{ "rgba16f",			GL_RGBA16F,			},
		{ "rgba16i",			GL_RGBA16I,			},
		{ "rgba16ui",			GL_RGBA16UI,		},
		{ "rgba8",				GL_RGBA8,			},
		{ "rgba8i",				GL_RGBA8I,			},
		{ "rgba8ui",			GL_RGBA8UI,			},
		{ "srgb8_alpha8",		GL_SRGB8_ALPHA8,	},
		{ "rgb10_a2",			GL_RGB10_A2,		},
		{ "rgb10_a2ui",			GL_RGB10_A2UI,		},
		{ "rgba4",				GL_RGBA4,			},
		{ "rgb5_a1",			GL_RGB5_A1,			},
		{ "rgba8_snorm",		GL_RGBA8_SNORM,		},
		{ "rgb8",				GL_RGB8,			},
		{ "rgb565",				GL_RGB565,			},
		{ "r11f_g11f_b10f",		GL_R11F_G11F_B10F,	},
		{ "rgb32f",				GL_RGB32F,			},
		{ "rgb32i",				GL_RGB32I,			},
		{ "rgb32ui",			GL_RGB32UI,			},
		{ "rgb16f",				GL_RGB16F,			},
		{ "rgb16i",				GL_RGB16I,			},
		{ "rgb16ui",			GL_RGB16UI,			},
		{ "rgb8_snorm",			GL_RGB8_SNORM,		},
		{ "rgb8i",				GL_RGB8I,			},
		{ "rgb8ui",				GL_RGB8UI,			},
		{ "srgb8",				GL_SRGB8,			},
		{ "rgb9_e5",			GL_RGB9_E5,			},
		{ "rg32f",				GL_RG32F,			},
		{ "rg32i",				GL_RG32I,			},
		{ "rg32ui",				GL_RG32UI,			},
		{ "rg16f",				GL_RG16F,			},
		{ "rg16i",				GL_RG16I,			},
		{ "rg16ui",				GL_RG16UI,			},
		{ "rg8",				GL_RG8,				},
		{ "rg8i",				GL_RG8I,			},
		{ "rg8ui",				GL_RG8UI,			},
		{ "rg8_snorm",			GL_RG8_SNORM,		},
		{ "r32f",				GL_R32F,			},
		{ "r32i",				GL_R32I,			},
		{ "r32ui",				GL_R32UI,			},
		{ "r16f",				GL_R16F,			},
		{ "r16i",				GL_R16I,			},
		{ "r16ui",				GL_R16UI,			},
		{ "r8",					GL_R8,				},
		{ "r8i",				GL_R8I,				},
		{ "r8ui",				GL_R8UI,			},
		{ "r8_snorm",			GL_R8_SNORM,		}
	};

	struct
	{
		const char*	name;
		deUint32	internalFormat;
	} sizedDepthStencilFormats[] =
	{
		// Depth and stencil formats
		{ "depth_component32f",	GL_DEPTH_COMPONENT32F	},
		{ "depth_component24",	GL_DEPTH_COMPONENT24	},
		{ "depth_component16",	GL_DEPTH_COMPONENT16	},
		{ "depth32f_stencil8",	GL_DEPTH32F_STENCIL8	},
		{ "depth24_stencil8",	GL_DEPTH24_STENCIL8		}
	};

	for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(sizedColorFormats); formatNdx++)
	{
		deUint32	internalFormat	= sizedColorFormats[formatNdx].internalFormat;
		string		nameBase		= sizedColorFormats[formatNdx].name;
		string		descriptionBase	= glu::getTextureFormatName(internalFormat);

		sizedCubeArrayGroup->addChild(new TextureCubeArrayFormatCase (m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), (nameBase + "_pot").c_str(),		(descriptionBase + ", GL_TEXTURE_CUBE_MAP_ARRAY").c_str(), internalFormat, 64, 12));
		sizedCubeArrayGroup->addChild(new TextureCubeArrayFormatCase (m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), (nameBase + "_npot").c_str(),	(descriptionBase + ", GL_TEXTURE_CUBE_MAP_ARRAY").c_str(), internalFormat, 64, 12));
	}

	for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(sizedDepthStencilFormats); formatNdx++)
	{
		deUint32	internalFormat	= sizedDepthStencilFormats[formatNdx].internalFormat;
		string		nameBase		= sizedDepthStencilFormats[formatNdx].name;
		string		descriptionBase	= glu::getTextureFormatName(internalFormat);

		sizedCubeArrayGroup->addChild(new TextureCubeArrayFormatCase (m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), (nameBase + "_pot").c_str(),		(descriptionBase + ", GL_TEXTURE_CUBE_MAP_ARRAY").c_str(), internalFormat, 64, 12));
		sizedCubeArrayGroup->addChild(new TextureCubeArrayFormatCase (m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), (nameBase + "_npot").c_str(),	(descriptionBase + ", GL_TEXTURE_CUBE_MAP_ARRAY").c_str(), internalFormat, 64, 12));
	}

	// \todo Check
	struct
	{
		const char*	name;
		deUint32	internalFormat;
	} bufferColorFormats[] =
	{
		{ "r8",					GL_R8,				},
		{ "r16f",				GL_R16F,			},
		{ "r32f",				GL_R32F,			},
		{ "r8i",				GL_R8I,				},
		{ "r16i",				GL_R16I,			},
		{ "r32i",				GL_R32I,			},
		{ "r8ui",				GL_R8UI,			},
		{ "r16ui",				GL_R16UI,			},
		{ "r32ui",				GL_R32UI,			},
		{ "rg8",				GL_RG8,				},
		{ "rg16f",				GL_RG16F,			},
		{ "rg32f",				GL_RG32F,			},
		{ "rg8i",				GL_RG8I,			},
		{ "rg16i",				GL_RG16I,			},
		{ "rg32i",				GL_RG32I,			},
		{ "rg8ui",				GL_RG8UI,			},
		{ "rg16ui",				GL_RG16UI,			},
		{ "rg32ui",				GL_RG32UI,			},
		{ "rgba8",				GL_RGBA8,			},
		{ "rgba16f",			GL_RGBA16F,			},
		{ "rgba32f",			GL_RGBA32F,			},
		{ "rgba8i",				GL_RGBA8I,			},
		{ "rgba16i",			GL_RGBA16I,			},
		{ "rgba32i",			GL_RGBA32I,			},
		{ "rgba8ui",			GL_RGBA8UI,			},
		{ "rgba16ui",			GL_RGBA16UI,		},
		{ "rgba32ui",			GL_RGBA32UI,		}
	};

	for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(bufferColorFormats); formatNdx++)
	{
		deUint32	internalFormat	= bufferColorFormats[formatNdx].internalFormat;
		string		nameBase		= bufferColorFormats[formatNdx].name;
		string		descriptionBase	= glu::getTextureFormatName(internalFormat);

		sizedBufferGroup->addChild	(new TextureBufferFormatCase	(m_context, m_context.getRenderContext(),	(nameBase + "_pot").c_str(),	(descriptionBase + ", GL_TEXTURE_BUFFER").c_str(),	internalFormat, 64));
		sizedBufferGroup->addChild	(new TextureBufferFormatCase	(m_context, m_context.getRenderContext(),	(nameBase + "_npot").c_str(),	(descriptionBase + ", GL_TEXTURE_BUFFER").c_str(),	internalFormat, 112));
	}
}

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