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

#include "es31fTextureFilteringTests.hpp"

#include "glsTextureTestUtil.hpp"

#include "gluPixelTransfer.hpp"
#include "gluTexture.hpp"
#include "gluTextureUtil.hpp"

#include "tcuCommandLine.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuImageCompare.hpp"
#include "tcuTexLookupVerifier.hpp"
#include "tcuVectorUtil.hpp"

#include "deStringUtil.hpp"
#include "deString.h"

#include "glwFunctions.hpp"
#include "glwEnums.hpp"

namespace deqp
{
namespace gles31
{
namespace Functional
{

using std::vector;
using std::string;
using tcu::TestLog;
using namespace gls::TextureTestUtil;

static const char* getFaceDesc (const tcu::CubeFace face)
{
	switch (face)
	{
		case tcu::CUBEFACE_NEGATIVE_X:	return "-X";
		case tcu::CUBEFACE_POSITIVE_X:	return "+X";
		case tcu::CUBEFACE_NEGATIVE_Y:	return "-Y";
		case tcu::CUBEFACE_POSITIVE_Y:	return "+Y";
		case tcu::CUBEFACE_NEGATIVE_Z:	return "-Z";
		case tcu::CUBEFACE_POSITIVE_Z:	return "+Z";
		default:
			DE_ASSERT(false);
			return DE_NULL;
	}
}

static void logCubeArrayTexCoords(TestLog& log, vector<float>& texCoord)
{
	const size_t numVerts = texCoord.size() / 4;

	DE_ASSERT(texCoord.size() % 4 == 0);

	for (size_t vertNdx = 0; vertNdx < numVerts; vertNdx++)
	{
		const size_t	coordNdx	= vertNdx * 4;

		const float		u			= texCoord[coordNdx + 0];
		const float		v			= texCoord[coordNdx + 1];
		const float		w			= texCoord[coordNdx + 2];
		const float		q			= texCoord[coordNdx + 3];

		log << TestLog::Message
			<< vertNdx << ": ("
			<< u << ", "
			<< v << ", "
			<< w << ", "
			<< q << ")"
			<< TestLog::EndMessage;
	}
}

// Cube map array filtering

class TextureCubeArrayFilteringCase : public TestCase
{
public:
									TextureCubeArrayFilteringCase	(Context& context,
																	 const char* name,
																	 const char* desc,
																	 deUint32 minFilter,
																	 deUint32 magFilter,
																	 deUint32 wrapS,
																	 deUint32 wrapT,
																	 deUint32 internalFormat,
																	 int size,
																	 int depth,
																	 bool onlySampleFaceInterior = false);

									~TextureCubeArrayFilteringCase	(void);

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

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

	const deUint32					m_minFilter;
	const deUint32					m_magFilter;
	const deUint32					m_wrapS;
	const deUint32					m_wrapT;

	const deUint32					m_internalFormat;
	const int						m_size;
	const int						m_depth;

	const bool						m_onlySampleFaceInterior; //!< If true, we avoid sampling anywhere near a face's edges.

	struct FilterCase
	{
		const glu::TextureCubeArray*	texture;
		tcu::Vec2						bottomLeft;
		tcu::Vec2						topRight;
		tcu::Vec2						layerRange;

		FilterCase (void)
			: texture(DE_NULL)
		{
		}

		FilterCase (const glu::TextureCubeArray* tex_, const tcu::Vec2& bottomLeft_, const tcu::Vec2& topRight_, const tcu::Vec2& layerRange_)
			: texture		(tex_)
			, bottomLeft	(bottomLeft_)
			, topRight		(topRight_)
			, layerRange	(layerRange_)
		{
		}
	};

	glu::TextureCubeArray*	m_gradientTex;
	glu::TextureCubeArray*	m_gridTex;

	TextureRenderer			m_renderer;

	std::vector<FilterCase>	m_cases;
	int						m_caseNdx;
};

TextureCubeArrayFilteringCase::TextureCubeArrayFilteringCase (Context& context,
															  const char* name,
															  const char* desc,
															  deUint32 minFilter,
															  deUint32 magFilter,
															  deUint32 wrapS,
															  deUint32 wrapT,
															  deUint32 internalFormat,
															  int size,
															  int depth,
															  bool onlySampleFaceInterior)
	: TestCase					(context, name, desc)
	, m_minFilter				(minFilter)
	, m_magFilter				(magFilter)
	, m_wrapS					(wrapS)
	, m_wrapT					(wrapT)
	, m_internalFormat			(internalFormat)
	, m_size					(size)
	, m_depth					(depth)
	, m_onlySampleFaceInterior	(onlySampleFaceInterior)
	, m_gradientTex				(DE_NULL)
	, m_gridTex					(DE_NULL)
	, m_renderer				(context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_310_ES, glu::PRECISION_HIGHP)
	, m_caseNdx					(0)
{
}

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

void TextureCubeArrayFilteringCase::init (void)
{
	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_cube_map_array"))
		throw tcu::NotSupportedError("GL_EXT_texture_cube_map_array not supported");

	try
	{
		const tcu::TextureFormat		texFmt		= glu::mapGLInternalFormat(m_internalFormat);
		const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(texFmt);
		const tcu::Vec4					cScale		= fmtInfo.valueMax-fmtInfo.valueMin;
		const tcu::Vec4					cBias		= fmtInfo.valueMin;
		const int						numLevels	= deLog2Floor32(m_size) + 1;
		const int						numLayers	= m_depth / 6;

		// Create textures.
		m_gradientTex	= new glu::TextureCubeArray(m_context.getRenderContext(), m_internalFormat, m_size, m_depth);
		m_gridTex		= new glu::TextureCubeArray(m_context.getRenderContext(), m_internalFormat, m_size, m_depth);

		const tcu::IVec4 levelSwz[] =
		{
			tcu::IVec4(0,1,2,3),
			tcu::IVec4(2,1,3,0),
			tcu::IVec4(3,0,1,2),
			tcu::IVec4(1,3,2,0),
		};

		// Fill first gradient texture (gradient direction varies between layers).
		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
		{
			m_gradientTex->getRefTexture().allocLevel(levelNdx);

			const tcu::PixelBufferAccess levelBuf = m_gradientTex->getRefTexture().getLevel(levelNdx);

			for (int layerFaceNdx = 0; layerFaceNdx < m_depth; layerFaceNdx++)
			{
				const tcu::IVec4	swz		= levelSwz[layerFaceNdx % DE_LENGTH_OF_ARRAY(levelSwz)];
				const tcu::Vec4		gMin	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f).swizzle(swz[0],swz[1],swz[2],swz[3])*cScale + cBias;
				const tcu::Vec4		gMax	= tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f).swizzle(swz[0],swz[1],swz[2],swz[3])*cScale + cBias;

				tcu::fillWithComponentGradients(tcu::getSubregion(levelBuf, 0, 0, layerFaceNdx, levelBuf.getWidth(), levelBuf.getHeight(), 1), gMin, gMax);
			}
		}

		// Fill second with grid texture (each layer has unique colors).
		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
		{
			m_gridTex->getRefTexture().allocLevel(levelNdx);

			const tcu::PixelBufferAccess levelBuf = m_gridTex->getRefTexture().getLevel(levelNdx);

			for (int layerFaceNdx = 0; layerFaceNdx < m_depth; layerFaceNdx++)
			{
				const deUint32	step	= 0x00ffffff / (numLevels*m_depth - 1);
				const deUint32	rgb		= step * (levelNdx + layerFaceNdx*numLevels);
				const deUint32	colorA	= 0xff000000 | rgb;
				const deUint32	colorB	= 0xff000000 | ~rgb;

				tcu::fillWithGrid(tcu::getSubregion(levelBuf, 0, 0, layerFaceNdx, levelBuf.getWidth(), levelBuf.getHeight(), 1),
								  4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
			}
		}

		// Upload.
		m_gradientTex->upload();
		m_gridTex->upload();

		// Test cases
		{
			const glu::TextureCubeArray* const	tex0	= m_gradientTex;
			const glu::TextureCubeArray* const	tex1	= m_gridTex;

			if (m_onlySampleFaceInterior)
			{
				m_cases.push_back(FilterCase(tex0, tcu::Vec2(-0.8f, -0.8f),	tcu::Vec2(0.8f,  0.8f),	tcu::Vec2(-0.5f, float(numLayers)+0.5f)));	// minification
				m_cases.push_back(FilterCase(tex0, tcu::Vec2(0.5f, 0.65f),	tcu::Vec2(0.8f,  0.8f),	tcu::Vec2(-0.5f, float(numLayers)+0.5f)));	// magnification
				m_cases.push_back(FilterCase(tex1, tcu::Vec2(-0.8f, -0.8f),	tcu::Vec2(0.8f,  0.8f),	tcu::Vec2(float(numLayers)+0.5f, -0.5f)));	// minification
				m_cases.push_back(FilterCase(tex1, tcu::Vec2(0.2f, 0.2f),	tcu::Vec2(0.6f,  0.5f),	tcu::Vec2(float(numLayers)+0.5f, -0.5f)));	// magnification
			}
			else
			{
				const bool isSingleSample = (m_context.getRenderTarget().getNumSamples() == 0);

				// minification - w/ tweak to avoid hitting triangle edges with a face switchpoint in multisample configs
				if (isSingleSample)
					m_cases.push_back(FilterCase(tex0, tcu::Vec2(-1.25f, -1.2f), tcu::Vec2(1.2f, 1.25f), tcu::Vec2(-0.5f, float(numLayers)+0.5f)));
				else
					m_cases.push_back(FilterCase(tex0, tcu::Vec2(-1.19f, -1.3f), tcu::Vec2(1.1f, 1.35f), tcu::Vec2(-0.5f, float(numLayers)+0.5f)));

				m_cases.push_back(FilterCase(tex0, tcu::Vec2(0.8f, 0.8f),		tcu::Vec2(1.25f, 1.20f),	tcu::Vec2(-0.5f, float(numLayers)+0.5f)));	// magnification
				m_cases.push_back(FilterCase(tex1, tcu::Vec2(-1.19f, -1.3f),	tcu::Vec2(1.1f, 1.35f),		tcu::Vec2(float(numLayers)+0.5f, -0.5f)));	// minification
				m_cases.push_back(FilterCase(tex1, tcu::Vec2(-1.2f, -1.1f),		tcu::Vec2(-0.8f, -0.8f),	tcu::Vec2(float(numLayers)+0.5f, -0.5f)));	// magnification

				// Layer rounding - only in single-sample configs as multisample configs may produce smooth transition at the middle.
				if (isSingleSample && (numLayers > 1))
					m_cases.push_back(FilterCase(tex0,	tcu::Vec2(-2.0f, -1.5f  ),	tcu::Vec2(-0.1f,  0.9f), tcu::Vec2(1.50001f, 1.49999f)));
			}
		}

		m_caseNdx = 0;
		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
	}
	catch (...)
	{
		// Clean up to save memory.
		TextureCubeArrayFilteringCase::deinit();
		throw;
	}
}

void TextureCubeArrayFilteringCase::deinit (void)
{
	delete m_gradientTex;
	delete m_gridTex;

	m_gradientTex	= DE_NULL;
	m_gridTex		= DE_NULL;

	m_renderer.clear();
	m_cases.clear();
}

TextureCubeArrayFilteringCase::IterateResult TextureCubeArrayFilteringCase::iterate (void)
{
	TestLog&						log				= m_testCtx.getLog();
	const glu::RenderContext&		renderCtx		= m_context.getRenderContext();
	const glw::Functions&			gl				= renderCtx.getFunctions();
	const int						viewportSize	= 28;
	const deUint32					randomSeed		= deStringHash(getName()) ^ deInt32Hash(m_caseNdx) ^ m_testCtx.getCommandLine().getBaseSeed();
	const RandomViewport			viewport		(m_context.getRenderTarget(), viewportSize, viewportSize, randomSeed);
	const FilterCase&				curCase			= m_cases[m_caseNdx];
	const tcu::TextureFormat		texFmt			= curCase.texture->getRefTexture().getFormat();
	const tcu::TextureFormatInfo	fmtInfo			= tcu::getTextureFormatInfo(texFmt);
	const tcu::ScopedLogSection		section			(m_testCtx.getLog(), string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
	ReferenceParams					refParams		(TEXTURETYPE_CUBE_ARRAY);

	if (viewport.width < viewportSize || viewport.height < viewportSize)
		throw tcu::NotSupportedError("Render target too small", "", __FILE__, __LINE__);

	// Params for reference computation.
	refParams.sampler					= glu::mapGLSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, m_minFilter, m_magFilter);
	refParams.sampler.seamlessCubeMap	= true;
	refParams.samplerType				= getSamplerType(texFmt);
	refParams.colorBias					= fmtInfo.lookupBias;
	refParams.colorScale				= fmtInfo.lookupScale;
	refParams.lodMode					= LODMODE_EXACT;

	gl.bindTexture	(GL_TEXTURE_CUBE_MAP_ARRAY, curCase.texture->getGLTexture());
	gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER,	m_minFilter);
	gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER,	m_magFilter);
	gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S,		m_wrapS);
	gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T,		m_wrapT);

	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);

	m_testCtx.getLog() << TestLog::Message << "Coordinates: " << curCase.bottomLeft << " -> " << curCase.topRight << TestLog::EndMessage;

	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
	{
		const tcu::CubeFace		face		= tcu::CubeFace(faceNdx);
		tcu::Surface			result		(viewport.width, viewport.height);
		vector<float>			texCoord;

		computeQuadTexCoordCubeArray(texCoord, face, curCase.bottomLeft, curCase.topRight, curCase.layerRange);

		log << TestLog::Message << "Face " << getFaceDesc(face) << TestLog::EndMessage;

		log << TestLog::Message << "Texture coordinates:" << TestLog::EndMessage;

		logCubeArrayTexCoords(log, texCoord);

		m_renderer.renderQuad(0, &texCoord[0], refParams);
		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");

		glu::readPixels(renderCtx, viewport.x, viewport.y, result.getAccess());
		GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels");

		{
			const bool				isNearestOnly	= m_minFilter == GL_NEAREST && m_magFilter == GL_NEAREST;
			const tcu::PixelFormat	pixelFormat		= renderCtx.getRenderTarget().getPixelFormat();
			const tcu::IVec4		coordBits		= tcu::IVec4(10);
			const tcu::IVec4		colorBits		= max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2), tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
			tcu::LodPrecision		lodPrecision;
			tcu::LookupPrecision	lookupPrecision;

			lodPrecision.derivateBits		= 10;
			lodPrecision.lodBits			= 5;
			lookupPrecision.colorThreshold	= tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
			lookupPrecision.coordBits		= coordBits.toWidth<3>();
			lookupPrecision.uvwBits			= tcu::IVec3(6);
			lookupPrecision.colorMask		= getCompareMask(pixelFormat);

			const bool isHighQuality = verifyTextureResult(m_testCtx, result.getAccess(), curCase.texture->getRefTexture(),
														   &texCoord[0], refParams, lookupPrecision, coordBits, lodPrecision, pixelFormat);

			if (!isHighQuality)
			{
				// Evaluate against lower precision requirements.
				lodPrecision.lodBits	= 4;
				lookupPrecision.uvwBits	= tcu::IVec3(4);

				m_testCtx.getLog() << TestLog::Message << "Warning: Verification against high precision requirements failed, trying with lower requirements." << TestLog::EndMessage;

				const bool isOk = verifyTextureResult(m_testCtx, result.getAccess(), curCase.texture->getRefTexture(),
													  &texCoord[0], refParams, lookupPrecision, coordBits, lodPrecision, pixelFormat);

				if (!isOk)
				{
					m_testCtx.getLog() << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
				}
				else if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
					m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality filtering result");
			}
		}
	}

	m_caseNdx += 1;
	return m_caseNdx < (int)m_cases.size() ? CONTINUE : STOP;
}

TextureFilteringTests::TextureFilteringTests (Context& context)
	: TestCaseGroup(context, "filtering", "Texture Filtering Tests")
{
}

TextureFilteringTests::~TextureFilteringTests (void)
{
}

void TextureFilteringTests::init (void)
{
	static const struct
	{
		const char*		name;
		deUint32		mode;
	} wrapModes[] =
	{
		{ "clamp",		GL_CLAMP_TO_EDGE },
		{ "repeat",		GL_REPEAT },
		{ "mirror",		GL_MIRRORED_REPEAT }
	};

	static const struct
	{
		const char*		name;
		deUint32		mode;
	} minFilterModes[] =
	{
		{ "nearest",				GL_NEAREST					},
		{ "linear",					GL_LINEAR					},
		{ "nearest_mipmap_nearest",	GL_NEAREST_MIPMAP_NEAREST	},
		{ "linear_mipmap_nearest",	GL_LINEAR_MIPMAP_NEAREST	},
		{ "nearest_mipmap_linear",	GL_NEAREST_MIPMAP_LINEAR	},
		{ "linear_mipmap_linear",	GL_LINEAR_MIPMAP_LINEAR		}
	};

	static const struct
	{
		const char*		name;
		deUint32		mode;
	} magFilterModes[] =
	{
		{ "nearest",	GL_NEAREST },
		{ "linear",		GL_LINEAR }
	};

	static const struct
	{
		int size;
		int depth;
	} sizesCubeArray[] =
	{
		{   8,	 6 },
		{  64,	12 },
		{ 128,	12 },
		{   7,	12 },
		{  63,	18 }
	};

	static const struct
	{
		const char*		name;
		deUint32		format;
	} filterableFormatsByType[] =
	{
		{ "rgba16f",		GL_RGBA16F			},
		{ "r11f_g11f_b10f",	GL_R11F_G11F_B10F	},
		{ "rgb9_e5",		GL_RGB9_E5			},
		{ "rgba8",			GL_RGBA8			},
		{ "rgba8_snorm",	GL_RGBA8_SNORM		},
		{ "rgb565",			GL_RGB565			},
		{ "rgba4",			GL_RGBA4			},
		{ "rgb5_a1",		GL_RGB5_A1			},
		{ "srgb8_alpha8",	GL_SRGB8_ALPHA8		},
		{ "rgb10_a2",		GL_RGB10_A2			}
	};

	// Cube map array texture filtering.
	{
		tcu::TestCaseGroup* const groupCubeArray = new tcu::TestCaseGroup(m_testCtx, "cube_array", "Cube Map Array Texture Filtering");
		addChild(groupCubeArray);

		// Formats.
		{
			tcu::TestCaseGroup* const formatsGroup = new tcu::TestCaseGroup(m_testCtx, "formats", "Cube Map Array Texture Formats");
			groupCubeArray->addChild(formatsGroup);

			for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
			{
				for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
				{
					const deUint32	minFilter	= minFilterModes[filterNdx].mode;
					const char*		filterName	= minFilterModes[filterNdx].name;
					const deUint32	format		= filterableFormatsByType[fmtNdx].format;
					const char*		formatName	= filterableFormatsByType[fmtNdx].name;
					const bool		isMipmap	= minFilter != GL_NEAREST && minFilter != GL_LINEAR;
					const deUint32	magFilter	= isMipmap ? GL_LINEAR : minFilter;
					const string	name		= string(formatName) + "_" + filterName;
					const deUint32	wrapS		= GL_REPEAT;
					const deUint32	wrapT		= GL_REPEAT;
					const int		size		= 64;
					const int		depth		= 12;

					formatsGroup->addChild(new TextureCubeArrayFilteringCase(m_context,
																			 name.c_str(), "",
																			 minFilter, magFilter,
																			 wrapS, wrapT,
																			 format,
																			 size, depth));
				}
			}
		}

		// Sizes.
		{
			tcu::TestCaseGroup* const sizesGroup = new tcu::TestCaseGroup(m_testCtx, "sizes", "Texture Sizes");
			groupCubeArray->addChild(sizesGroup);

			for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizesCubeArray); sizeNdx++)
			{
				for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
				{
					const deUint32	minFilter	= minFilterModes[filterNdx].mode;
					const char*		filterName	= minFilterModes[filterNdx].name;
					const deUint32	format		= GL_RGBA8;
					const bool		isMipmap	= minFilter != GL_NEAREST && minFilter != GL_LINEAR;
					const deUint32	magFilter	= isMipmap ? GL_LINEAR : minFilter;
					const deUint32	wrapS		= GL_REPEAT;
					const deUint32	wrapT		= GL_REPEAT;
					const int		size		= sizesCubeArray[sizeNdx].size;
					const int		depth		= sizesCubeArray[sizeNdx].depth;
					const string	name		= de::toString(size) + "x" + de::toString(size) + "x" + de::toString(depth) + "_" + filterName;

					sizesGroup->addChild(new TextureCubeArrayFilteringCase(m_context,
																		   name.c_str(), "",
																		   minFilter, magFilter,
																		   wrapS, wrapT,
																		   format,
																		   size, depth));
				}
			}
		}

		// Wrap modes.
		{
			tcu::TestCaseGroup* const combinationsGroup = new tcu::TestCaseGroup(m_testCtx, "combinations", "Filter and wrap mode combinations");
			groupCubeArray->addChild(combinationsGroup);

			for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
			{
				for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
				{
					for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
					{
						for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
						{
							const deUint32	minFilter	= minFilterModes[minFilterNdx].mode;
							const deUint32	magFilter	= magFilterModes[magFilterNdx].mode;
							const deUint32	format		= GL_RGBA8;
							const deUint32	wrapS		= wrapModes[wrapSNdx].mode;
							const deUint32	wrapT		= wrapModes[wrapTNdx].mode;
							const int		size		= 63;
							const int		depth		= 12;
							const string	name		= string(minFilterModes[minFilterNdx].name) + "_" + magFilterModes[magFilterNdx].name + "_" + wrapModes[wrapSNdx].name + "_" + wrapModes[wrapTNdx].name;

							combinationsGroup->addChild(new TextureCubeArrayFilteringCase(m_context,
																						  name.c_str(), "",
																						  minFilter, magFilter,
																						  wrapS, wrapT,
																						  format,
																						  size, depth));
						}
					}
				}
			}
		}

		// Cases with no visible cube edges.
		{
			tcu::TestCaseGroup* const onlyFaceInteriorGroup = new tcu::TestCaseGroup(m_testCtx, "no_edges_visible", "Don't sample anywhere near a face's edges");
			groupCubeArray->addChild(onlyFaceInteriorGroup);

			for (int isLinearI = 0; isLinearI <= 1; isLinearI++)
			{
				const bool		isLinear	= isLinearI != 0;
				const deUint32	filter		= isLinear ? GL_LINEAR : GL_NEAREST;

				onlyFaceInteriorGroup->addChild(new TextureCubeArrayFilteringCase(m_context,
																				  isLinear ? "linear" : "nearest", "",
																				  filter, filter,
																				  GL_REPEAT, GL_REPEAT,
																				  GL_RGBA8,
																				  63, 12,
																				  true));
			}
		}
	}
}

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