1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Texture wrap mode tests.
22 *//*--------------------------------------------------------------------*/
23
24#include "es3fTextureWrapTests.hpp"
25#include "glsTextureTestUtil.hpp"
26#include "gluTexture.hpp"
27#include "gluStrUtil.hpp"
28#include "gluTextureUtil.hpp"
29#include "gluPixelTransfer.hpp"
30#include "tcuTestLog.hpp"
31#include "tcuTextureUtil.hpp"
32#include "tcuCompressedTexture.hpp"
33#include "tcuVectorUtil.hpp"
34#include "tcuTexLookupVerifier.hpp"
35#include "deRandom.hpp"
36#include "deStringUtil.hpp"
37#include "deMemory.h"
38
39#include "glwEnums.hpp"
40#include "glwFunctions.hpp"
41
42namespace deqp
43{
44namespace gles3
45{
46namespace Functional
47{
48
49using tcu::TestLog;
50using tcu::CompressedTexture;
51using std::vector;
52using std::string;
53using tcu::Sampler;
54using namespace glu;
55using namespace gls::TextureTestUtil;
56
57//! Checks whether any ASTC version (LDR, HDR, full) is supported.
58static inline bool isASTCSupported (const glu::ContextInfo& contextInfo)
59{
60	const vector<string>& extensions = contextInfo.getExtensions();
61
62	for (int extNdx = 0; extNdx < (int)extensions.size(); extNdx++)
63	{
64		const string& ext = extensions[extNdx];
65
66		if (ext == "GL_KHR_texture_compression_astc_ldr" ||
67			ext == "GL_KHR_texture_compression_astc_hdr" ||
68			ext == "GL_OES_texture_compression_astc")
69			return true;
70	}
71
72	return false;
73}
74
75enum
76{
77	VIEWPORT_WIDTH		= 256,
78	VIEWPORT_HEIGHT		= 256
79};
80
81class TextureWrapCase : public tcu::TestCase
82{
83public:
84									TextureWrapCase			(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* description, deUint32 format, deUint32 dataType, deUint32 wrapS, deUint32 wrapT, deUint32 minFilter, deUint32 magFilter, int width, int height);
85									TextureWrapCase			(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* description, deUint32 wrapS, deUint32 wrapT, deUint32 minFilter, deUint32 magFilter, const std::vector<std::string>& filenames);
86									TextureWrapCase			(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* description, CompressedTexture::Format compressedFormat, deUint32 wrapS, deUint32 wrapT, deUint32 minFilter, deUint32 magFilter, int width, int height);
87									~TextureWrapCase		(void);
88
89	void							init					(void);
90	void							deinit					(void);
91	IterateResult					iterate					(void);
92
93private:
94									TextureWrapCase			(const TextureWrapCase& other);
95	TextureWrapCase&				operator=				(const TextureWrapCase& other);
96
97	struct Case
98	{
99		tcu::Vec2 bottomLeft;
100		tcu::Vec2 topRight;
101
102		Case (void) {}
103		Case (const tcu::Vec2& bl, const tcu::Vec2& tr) : bottomLeft(bl), topRight(tr) {}
104	};
105
106	glu::RenderContext&				m_renderCtx;
107	const glu::ContextInfo&			m_renderCtxInfo;
108
109	const deUint32					m_format;
110	const deUint32					m_dataType;
111	const CompressedTexture::Format	m_compressedFormat;
112	const deUint32					m_wrapS;
113	const deUint32					m_wrapT;
114	const deUint32					m_minFilter;
115	const deUint32					m_magFilter;
116
117	int								m_width;
118	int								m_height;
119	const std::vector<std::string>	m_filenames;
120
121	vector<Case>					m_cases;
122	int								m_caseNdx;
123
124	glu::Texture2D*					m_texture;
125	TextureRenderer					m_renderer;
126};
127
128TextureWrapCase::TextureWrapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* description, deUint32 format, deUint32 dataType, deUint32 wrapS, deUint32 wrapT, deUint32 minFilter, deUint32 magFilter, int width, int height)
129	: TestCase				(testCtx, name, description)
130	, m_renderCtx			(renderCtx)
131	, m_renderCtxInfo		(ctxInfo)
132	, m_format				(format)
133	, m_dataType			(dataType)
134	, m_compressedFormat	(CompressedTexture::FORMAT_LAST)
135	, m_wrapS				(wrapS)
136	, m_wrapT				(wrapT)
137	, m_minFilter			(minFilter)
138	, m_magFilter			(magFilter)
139	, m_width				(width)
140	, m_height				(height)
141	, m_caseNdx				(0)
142	, m_texture				(DE_NULL)
143	, m_renderer			(renderCtx, testCtx, glu::GLSL_VERSION_300_ES, glu::PRECISION_MEDIUMP)
144{
145}
146
147TextureWrapCase::TextureWrapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* description, deUint32 wrapS, deUint32 wrapT, deUint32 minFilter, deUint32 magFilter, const std::vector<std::string>& filenames)
148	: TestCase				(testCtx, name, description)
149	, m_renderCtx			(renderCtx)
150	, m_renderCtxInfo		(ctxInfo)
151	, m_format				(GL_NONE)
152	, m_dataType			(GL_NONE)
153	, m_compressedFormat	(CompressedTexture::FORMAT_LAST)
154	, m_wrapS				(wrapS)
155	, m_wrapT				(wrapT)
156	, m_minFilter			(minFilter)
157	, m_magFilter			(magFilter)
158	, m_width				(0)
159	, m_height				(0)
160	, m_filenames			(filenames)
161	, m_caseNdx				(0)
162	, m_texture				(DE_NULL)
163	, m_renderer			(renderCtx, testCtx, glu::GLSL_VERSION_300_ES, glu::PRECISION_MEDIUMP)
164{
165}
166
167TextureWrapCase::TextureWrapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* description, CompressedTexture::Format compressedFormat, deUint32 wrapS, deUint32 wrapT, deUint32 minFilter, deUint32 magFilter, int width, int height)
168	: TestCase				(testCtx, name, description)
169	, m_renderCtx			(renderCtx)
170	, m_renderCtxInfo		(ctxInfo)
171	, m_format				(GL_NONE)
172	, m_dataType			(GL_NONE)
173	, m_compressedFormat	(compressedFormat)
174	, m_wrapS				(wrapS)
175	, m_wrapT				(wrapT)
176	, m_minFilter			(minFilter)
177	, m_magFilter			(magFilter)
178	, m_width				(width)
179	, m_height				(height)
180	, m_caseNdx				(0)
181	, m_texture				(DE_NULL)
182	, m_renderer			(renderCtx, testCtx, glu::GLSL_VERSION_300_ES, glu::PRECISION_MEDIUMP)
183{
184}
185
186
187TextureWrapCase::~TextureWrapCase (void)
188{
189	deinit();
190}
191
192void TextureWrapCase::init (void)
193{
194	// Load or generate texture.
195
196	if (!m_filenames.empty())
197	{
198		// Load compressed texture from file.
199
200		DE_ASSERT(m_width == 0 && m_height == 0 && m_format == GL_NONE && m_dataType == GL_NONE);
201
202		m_texture	= glu::Texture2D::create(m_renderCtx, m_renderCtxInfo, m_testCtx.getArchive(), (int)m_filenames.size(), m_filenames);
203		m_width		= m_texture->getRefTexture().getWidth();
204		m_height	= m_texture->getRefTexture().getHeight();
205	}
206	else if (m_compressedFormat != CompressedTexture::FORMAT_LAST)
207	{
208		// Generate compressed texture.
209
210		DE_ASSERT(m_format == GL_NONE && m_dataType == GL_NONE);
211
212		if (tcu::isEtcFormat(m_compressedFormat))
213		{
214			// Create ETC texture. Any content is valid.
215
216			tcu::CompressedTexture	compressedTexture	(m_compressedFormat, m_width, m_height);
217			const int				dataSize			= compressedTexture.getDataSize();
218			deUint8* const			data				= (deUint8*)compressedTexture.getData();
219			de::Random				rnd					(deStringHash(getName()));
220
221			for (int i = 0; i < dataSize; i++)
222				data[i] = rnd.getUint32() & 0xff;
223
224			m_texture = new glu::Texture2D(m_renderCtx, m_renderCtxInfo, 1, &compressedTexture);
225		}
226		else if (tcu::isASTCFormat(m_compressedFormat))
227		{
228			// Create ASTC texture by picking from a set of pre-generated blocks.
229
230			static const int		BLOCK_SIZE				= 16;
231			static const deUint8	blocks[][BLOCK_SIZE]	=
232			{
233				// \note All of the following blocks are valid in LDR mode.
234				{ 252,	253,	255,	255,	255,	255,	255,	255,	8,		71,		90,		78,		22,		17,		26,		66,		},
235				{ 252,	253,	255,	255,	255,	255,	255,	255,	220,	74,		139,	235,	249,	6,		145,	125		},
236				{ 252,	253,	255,	255,	255,	255,	255,	255,	223,	251,	28,		206,	54,		251,	160,	174		},
237				{ 252,	253,	255,	255,	255,	255,	255,	255,	39,		4,		153,	219,	180,	61,		51,		37		},
238				{ 67,	2,		0,		254,	1,		0,		64,		215,	83,		211,	159,	105,	41,		140,	50,		2		},
239				{ 67,	130,	0,		170,	84,		255,	65,		215,	83,		211,	159,	105,	41,		140,	50,		2		},
240				{ 67,	2,		129,	38,		51,		229,	95,		215,	83,		211,	159,	105,	41,		140,	50,		2		},
241				{ 67,	130,	193,	56,		213,	144,	95,		215,	83,		211,	159,	105,	41,		140,	50,		2		}
242			};
243
244			if (!isASTCSupported(m_renderCtxInfo)) // \note Any level of ASTC support is enough, since we're only using LDR blocks.
245				throw tcu::NotSupportedError("ASTC not supported");
246
247			tcu::CompressedTexture	compressedTexture	(m_compressedFormat, m_width, m_height);
248			const int				dataSize			= compressedTexture.getDataSize();
249			deUint8* const			data				= (deUint8*)compressedTexture.getData();
250			de::Random				rnd					(deStringHash(getName()));
251			DE_ASSERT(dataSize % BLOCK_SIZE == 0);
252
253			for (int i = 0; i < dataSize/BLOCK_SIZE; i++)
254				deMemcpy(&data[i*BLOCK_SIZE], &blocks[rnd.getInt(0, DE_LENGTH_OF_ARRAY(blocks)-1)][0], BLOCK_SIZE);
255
256			m_texture = new glu::Texture2D(m_renderCtx, m_renderCtxInfo, 1, &compressedTexture);
257		}
258		else
259			DE_ASSERT(false);
260	}
261	else
262	{
263		m_texture = new Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height);
264
265		// Fill level 0.
266		m_texture->getRefTexture().allocLevel(0);
267		tcu::fillWithComponentGradients(m_texture->getRefTexture().getLevel(0), tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f));
268
269		m_texture->upload();
270	}
271
272	// Sub-cases.
273
274	m_cases.push_back(Case(tcu::Vec2(-1.5f, -3.0f), tcu::Vec2(1.5f, 2.5f)));
275	m_cases.push_back(Case(tcu::Vec2(-0.5f, 0.75f), tcu::Vec2(0.25f, 1.25f)));
276	DE_ASSERT(m_caseNdx == 0);
277
278	// Initialize to success, set to failure later if needed.
279
280	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
281}
282
283void TextureWrapCase::deinit (void)
284{
285	delete m_texture;
286	m_texture = DE_NULL;
287
288	m_renderer.clear();
289}
290
291TextureWrapCase::IterateResult TextureWrapCase::iterate (void)
292{
293	const glw::Functions&			gl								= m_renderCtx.getFunctions();
294	TestLog&						log								= m_testCtx.getLog();
295	const RandomViewport			viewport						(m_renderCtx.getRenderTarget(), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, deStringHash(getName()) + m_caseNdx);
296	tcu::Surface					renderedFrame					(viewport.width, viewport.height);
297	tcu::Surface					referenceFrame					(viewport.width, viewport.height);
298	ReferenceParams					refParams						(TEXTURETYPE_2D);
299	const tcu::TextureFormat		texFormat						= m_texture->getRefTexture().getFormat();
300	vector<float>					texCoord;
301	const tcu::TextureFormatInfo	texFormatInfo					= tcu::getTextureFormatInfo(texFormat);
302	// \note For non-sRGB ASTC formats, the values are fp16 in range [0..1], not the range assumed given by tcu::getTextureFormatInfo().
303	const bool						useDefaultColorScaleAndBias		= !tcu::isASTCFormat(m_compressedFormat) || tcu::isASTCSRGBFormat(m_compressedFormat);
304
305	// Bind to unit 0.
306	gl.activeTexture(GL_TEXTURE0);
307	gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());
308
309	// Setup filtering and wrap modes.
310	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		m_wrapS);
311	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		m_wrapT);
312	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	m_minFilter);
313	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	m_magFilter);
314
315	GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
316
317	// Parameters for reference images.
318	refParams.sampler		= mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter);
319	refParams.lodMode		= LODMODE_EXACT;
320	refParams.samplerType	= getSamplerType(m_texture->getRefTexture().getFormat());
321	refParams.colorScale	= useDefaultColorScaleAndBias ? texFormatInfo.lookupScale	: tcu::Vec4(1.0f);
322	refParams.colorBias		= useDefaultColorScaleAndBias ? texFormatInfo.lookupBias	: tcu::Vec4(0.0f);
323
324	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
325	computeQuadTexCoord2D(texCoord, m_cases[m_caseNdx].bottomLeft, m_cases[m_caseNdx].topRight);
326	m_renderer.renderQuad(0, &texCoord[0], refParams);
327	glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
328
329	{
330		const tcu::ScopedLogSection		section			(log, string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
331		const bool						isNearestOnly	= m_minFilter == GL_NEAREST && m_magFilter == GL_NEAREST;
332		const bool						isSRGB			= texFormat.order == tcu::TextureFormat::sRGB || texFormat.order == tcu::TextureFormat::sRGBA;
333		const tcu::PixelFormat			pixelFormat		= m_renderCtx.getRenderTarget().getPixelFormat();
334		const tcu::IVec4				colorBits		= tcu::max(getBitsVec(pixelFormat) - (isNearestOnly && !isSRGB ? 1 : 2), tcu::IVec4(0));
335		tcu::LodPrecision				lodPrecision;
336		tcu::LookupPrecision			lookupPrecision;
337
338		lodPrecision.derivateBits		= 18;
339		lodPrecision.lodBits			= 5;
340		lookupPrecision.colorThreshold	= tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
341		lookupPrecision.coordBits		= tcu::IVec3(20,20,0);
342		lookupPrecision.uvwBits			= tcu::IVec3(5,5,0);
343		lookupPrecision.colorMask		= getCompareMask(pixelFormat);
344
345		log << TestLog::Message << "Note: lookup coordinates: bottom-left " << m_cases[m_caseNdx].bottomLeft << ", top-right " << m_cases[m_caseNdx].topRight << TestLog::EndMessage;
346
347		const bool isOk = verifyTextureResult(m_testCtx, renderedFrame.getAccess(), m_texture->getRefTexture(),
348											  &texCoord[0], refParams, lookupPrecision, lodPrecision, pixelFormat);
349
350		if (!isOk)
351			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
352	}
353
354	m_caseNdx++;
355	return m_caseNdx < (int)m_cases.size() ? CONTINUE : STOP;
356}
357
358TextureWrapTests::TextureWrapTests (Context& context)
359	: TestCaseGroup(context, "wrap", "Wrap Mode Tests")
360{
361}
362
363TextureWrapTests::~TextureWrapTests (void)
364{
365}
366
367void TextureWrapTests::init (void)
368{
369	static const struct
370	{
371		const char*		name;
372		deUint32		mode;
373	} wrapModes[] =
374	{
375		{ "clamp",		GL_CLAMP_TO_EDGE },
376		{ "repeat",		GL_REPEAT },
377		{ "mirror",		GL_MIRRORED_REPEAT }
378	};
379
380	static const struct
381	{
382		const char*		name;
383		deUint32		mode;
384	} filteringModes[] =
385	{
386		{ "nearest",	GL_NEAREST },
387		{ "linear",		GL_LINEAR }
388	};
389
390#define FOR_EACH(ITERATOR, ARRAY, BODY)	\
391	for (int ITERATOR = 0; ITERATOR < DE_LENGTH_OF_ARRAY(ARRAY); ITERATOR++)	\
392		BODY
393
394	// RGBA8 cases.
395	{
396		static const struct
397		{
398			const char*		name;
399			int				width;
400			int				height;
401		} rgba8Sizes[] =
402		{
403			{ "pot",		64, 128 },
404			{ "npot",		63, 112 }
405		};
406
407		{
408			TestCaseGroup* const rgba8Group = new TestCaseGroup(m_context, "rgba8", "");
409			addChild(rgba8Group);
410
411			FOR_EACH(size,		rgba8Sizes,
412			FOR_EACH(wrapS,		wrapModes,
413			FOR_EACH(wrapT,		wrapModes,
414			FOR_EACH(filter,	filteringModes,
415				{
416					const string name = string("") + wrapModes[wrapS].name + "_" + wrapModes[wrapT].name + "_" + filteringModes[filter].name + "_" + rgba8Sizes[size].name;
417					rgba8Group->addChild(new TextureWrapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), name.c_str(), "",
418															 GL_RGBA, GL_UNSIGNED_BYTE,
419															 wrapModes[wrapS].mode,
420															 wrapModes[wrapT].mode,
421															 filteringModes[filter].mode, filteringModes[filter].mode,
422															 rgba8Sizes[size].width, rgba8Sizes[size].height));
423
424				}))));
425		}
426	}
427
428	// ETC1 cases.
429	{
430		TestCaseGroup* const etc1Group = new TestCaseGroup(m_context, "etc1", "");
431		addChild(etc1Group);
432
433		// Power-of-two ETC1 texture
434		std::vector<std::string> potFilenames;
435		potFilenames.push_back("data/etc1/photo_helsinki_mip_0.pkm");
436
437		FOR_EACH(wrapS,		wrapModes,
438		FOR_EACH(wrapT,		wrapModes,
439		FOR_EACH(filter,	filteringModes,
440			{
441				const string name = string("") + wrapModes[wrapS].name + "_" + wrapModes[wrapT].name + "_" + filteringModes[filter].name + "_pot";
442				etc1Group->addChild(new TextureWrapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), name.c_str(), "",
443														wrapModes[wrapS].mode,
444														wrapModes[wrapT].mode,
445														filteringModes[filter].mode, filteringModes[filter].mode,
446														potFilenames));
447
448			})));
449
450		std::vector<std::string> npotFilenames;
451		npotFilenames.push_back("data/etc1/photo_helsinki_113x89.pkm");
452
453		// NPOT ETC1 texture
454		FOR_EACH(wrapS,		wrapModes,
455		FOR_EACH(wrapT,		wrapModes,
456		FOR_EACH(filter,	filteringModes,
457			{
458				const string name = string("") + wrapModes[wrapS].name + "_" + wrapModes[wrapT].name + "_" + filteringModes[filter].name + "_npot";
459				etc1Group->addChild(new TextureWrapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), name.c_str(), "",
460														wrapModes[wrapS].mode,
461														wrapModes[wrapT].mode,
462														filteringModes[filter].mode, filteringModes[filter].mode,
463														npotFilenames));
464			})));
465	}
466
467	// ETC-2 (and EAC) cases.
468	{
469		static const struct
470		{
471			const char*					name;
472			CompressedTexture::Format	format;
473		} etc2Formats[] =
474		{
475			{ "eac_r11",							CompressedTexture::EAC_R11,							},
476			{ "eac_signed_r11",						CompressedTexture::EAC_SIGNED_R11,					},
477			{ "eac_rg11",							CompressedTexture::EAC_RG11,						},
478			{ "eac_signed_rg11",					CompressedTexture::EAC_SIGNED_RG11,					},
479			{ "etc2_rgb8",							CompressedTexture::ETC2_RGB8,						},
480			{ "etc2_srgb8",							CompressedTexture::ETC2_SRGB8,						},
481			{ "etc2_rgb8_punchthrough_alpha1",		CompressedTexture::ETC2_RGB8_PUNCHTHROUGH_ALPHA1,	},
482			{ "etc2_srgb8_punchthrough_alpha1",		CompressedTexture::ETC2_SRGB8_PUNCHTHROUGH_ALPHA1,	},
483			{ "etc2_eac_rgba8",						CompressedTexture::ETC2_EAC_RGBA8,					},
484			{ "etc2_eac_srgb8_alpha8",				CompressedTexture::ETC2_EAC_SRGB8_ALPHA8,			}
485		};
486
487		static const struct
488		{
489			const char*		name;
490			int				width;
491			int				height;
492		} etc2Sizes[] =
493		{
494			{ "pot",	64,		128	},
495			{ "npot",	123,	107	}
496		};
497
498		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(etc2Formats); formatNdx++)
499		{
500			TestCaseGroup* const formatGroup = new TestCaseGroup(m_context, etc2Formats[formatNdx].name, "");
501			addChild(formatGroup);
502
503			FOR_EACH(size,		etc2Sizes,
504			FOR_EACH(wrapS,		wrapModes,
505			FOR_EACH(wrapT,		wrapModes,
506			FOR_EACH(filter,	filteringModes,
507				{
508					const string name = string("") + wrapModes[wrapS].name + "_" + wrapModes[wrapT].name + "_" + filteringModes[filter].name + "_" + etc2Sizes[size].name;
509					formatGroup->addChild(new TextureWrapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), name.c_str(), "",
510															  etc2Formats[formatNdx].format,
511															  wrapModes[wrapS].mode,
512															  wrapModes[wrapT].mode,
513															  filteringModes[filter].mode, filteringModes[filter].mode,
514															  etc2Sizes[size].width, etc2Sizes[size].height));
515				}))));
516		}
517	}
518
519	// ASTC cases.
520	{
521		for (int formatI = 0; formatI < CompressedTexture::FORMAT_LAST; formatI++)
522		{
523			const CompressedTexture::Format format = (CompressedTexture::Format)formatI;
524			if (!tcu::isASTCFormat(format))
525				continue;
526
527			{
528				const tcu::IVec3		blockSize		= tcu::getASTCBlockSize(format);
529				const string			formatName		= "astc_" + de::toString(blockSize.x()) + "x" + de::toString(blockSize.y()) + (tcu::isASTCSRGBFormat(format) ? "_srgb" : "");
530				TestCaseGroup* const	formatGroup		= new TestCaseGroup(m_context, formatName.c_str(), "");
531				addChild(formatGroup);
532
533				DE_ASSERT(blockSize.z() == 1);
534
535				// \note This array is NOT static.
536				const struct
537				{
538					const char*		name;
539					int				width;
540					int				height;
541				} formatSizes[] =
542				{
543					{ "divisible",		blockSize.x()*10,		blockSize.y()*10	},
544					{ "not_divisible",	blockSize.x()*10+1,		blockSize.y()*10+1	},
545				};
546
547				FOR_EACH(size,		formatSizes,
548				FOR_EACH(wrapS,		wrapModes,
549				FOR_EACH(wrapT,		wrapModes,
550				FOR_EACH(filter,	filteringModes,
551					{
552						string name = string("") + wrapModes[wrapS].name + "_" + wrapModes[wrapT].name + "_" + filteringModes[filter].name + "_" + formatSizes[size].name;
553						formatGroup->addChild(new TextureWrapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), name.c_str(), "",
554																  format,
555																  wrapModes[wrapS].mode,
556																  wrapModes[wrapT].mode,
557																  filteringModes[filter].mode, filteringModes[filter].mode,
558																  formatSizes[size].width, formatSizes[size].height));
559					}))));
560			}
561		}
562	}
563}
564
565} // Functional
566} // gles3
567} // deqp
568