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 specification tests.
22 *
23 * \todo [pyry] Following tests are missing:
24 *  - Specify mipmap incomplete texture, use without mipmaps, re-specify
25 *    as complete and render.
26 *  - Randomly re-specify levels to eventually reach mipmap-complete texture.
27 *//*--------------------------------------------------------------------*/
28
29#include "es31fTextureSpecificationTests.hpp"
30#include "tcuTestLog.hpp"
31#include "tcuImageCompare.hpp"
32#include "tcuTextureUtil.hpp"
33#include "tcuVectorUtil.hpp"
34#include "gluStrUtil.hpp"
35#include "gluTexture.hpp"
36#include "gluTextureUtil.hpp"
37#include "sglrContextUtil.hpp"
38#include "sglrContextWrapper.hpp"
39#include "sglrGLContext.hpp"
40#include "sglrReferenceContext.hpp"
41#include "glsTextureTestUtil.hpp"
42#include "deRandom.hpp"
43#include "deStringUtil.hpp"
44
45// \todo [2012-04-29 pyry] Should be named SglrUtil
46#include "es31fFboTestUtil.hpp"
47
48#include "glwEnums.hpp"
49
50namespace deqp
51{
52namespace gles31
53{
54namespace Functional
55{
56
57using std::string;
58using std::vector;
59using std::pair;
60using tcu::TestLog;
61using tcu::Vec4;
62using tcu::IVec4;
63using tcu::UVec4;
64using namespace FboTestUtil;
65
66enum
67{
68	VIEWPORT_WIDTH	= 256,
69	VIEWPORT_HEIGHT	= 256
70};
71
72static inline int maxLevelCount (int size)
73{
74	return (int)deLog2Floor32(size)+1;
75}
76
77template <int Size>
78static tcu::Vector<float, Size> randomVector (de::Random& rnd, const tcu::Vector<float, Size>& minVal = tcu::Vector<float, Size>(0.0f), const tcu::Vector<float, Size>& maxVal = tcu::Vector<float, Size>(1.0f))
79{
80	tcu::Vector<float, Size> res;
81	for (int ndx = 0; ndx < Size; ndx++)
82		res[ndx] = rnd.getFloat(minVal[ndx], maxVal[ndx]);
83	return res;
84}
85
86static tcu::CubeFace getCubeFaceFromNdx (int ndx)
87{
88	switch (ndx)
89	{
90		case 0:	return tcu::CUBEFACE_POSITIVE_X;
91		case 1:	return tcu::CUBEFACE_NEGATIVE_X;
92		case 2:	return tcu::CUBEFACE_POSITIVE_Y;
93		case 3:	return tcu::CUBEFACE_NEGATIVE_Y;
94		case 4:	return tcu::CUBEFACE_POSITIVE_Z;
95		case 5:	return tcu::CUBEFACE_NEGATIVE_Z;
96		default:
97			DE_ASSERT(false);
98			return tcu::CUBEFACE_LAST;
99	}
100}
101
102class TextureSpecCase : public TestCase, public sglr::ContextWrapper
103{
104public:
105						TextureSpecCase			(Context& context, const char* name, const char* desc);
106						~TextureSpecCase		(void);
107
108	IterateResult		iterate					(void);
109
110protected:
111	virtual bool		checkExtensionSupport	(void)	{ return true; }
112
113	virtual void		createTexture			(void)																= DE_NULL;
114	virtual void		verifyTexture			(sglr::GLContext& gles3Context, sglr::ReferenceContext& refContext)	= DE_NULL;
115
116	// Utilities.
117	void				renderTex				(tcu::Surface& dst, deUint32 program, int width, int height);
118	void				readPixels				(tcu::Surface& dst, int x, int y, int width, int height);
119
120private:
121						TextureSpecCase			(const TextureSpecCase& other);
122	TextureSpecCase&	operator=				(const TextureSpecCase& other);
123};
124
125TextureSpecCase::TextureSpecCase (Context& context, const char* name, const char* desc)
126	: TestCase(context, name, desc)
127{
128}
129
130TextureSpecCase::~TextureSpecCase (void)
131{
132}
133
134TextureSpecCase::IterateResult TextureSpecCase::iterate (void)
135{
136	glu::RenderContext&			renderCtx				= TestCase::m_context.getRenderContext();
137	const tcu::RenderTarget&	renderTarget			= renderCtx.getRenderTarget();
138	tcu::TestLog&				log						= m_testCtx.getLog();
139
140	if (renderTarget.getWidth() < VIEWPORT_WIDTH || renderTarget.getHeight() < VIEWPORT_HEIGHT)
141		throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
142
143	if (!checkExtensionSupport())
144		throw tcu::NotSupportedError("Extension not supported", "", __FILE__, __LINE__);
145
146	// Context size, and viewport for GLES3.1
147	de::Random	rnd			(deStringHash(getName()));
148	int			width		= deMin32(renderTarget.getWidth(),	VIEWPORT_WIDTH);
149	int			height		= deMin32(renderTarget.getHeight(),	VIEWPORT_HEIGHT);
150	int			x			= rnd.getInt(0, renderTarget.getWidth()		- width);
151	int			y			= rnd.getInt(0, renderTarget.getHeight()	- height);
152
153	// Contexts.
154	sglr::GLContext					gles31Context	(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height));
155	sglr::ReferenceContextBuffers	refBuffers		(tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), 0 /* depth */, 0 /* stencil */, width, height);
156	sglr::ReferenceContext			refContext		(sglr::ReferenceContextLimits(renderCtx), refBuffers.getColorbuffer(), refBuffers.getDepthbuffer(), refBuffers.getStencilbuffer());
157
158	// Clear color buffer.
159	for (int ndx = 0; ndx < 2; ndx++)
160	{
161		setContext(ndx ? (sglr::Context*)&refContext : (sglr::Context*)&gles31Context);
162		glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
163		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
164	}
165
166	// Construct texture using both GLES3.1 and reference contexts.
167	for (int ndx = 0; ndx < 2; ndx++)
168	{
169		setContext(ndx ? (sglr::Context*)&refContext : (sglr::Context*)&gles31Context);
170		createTexture();
171		TCU_CHECK(glGetError() == GL_NO_ERROR);
172	}
173
174	// Initialize case result to pass.
175	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
176
177	// Disable logging.
178	gles31Context.enableLogging(0);
179
180	// Verify results.
181	verifyTexture(gles31Context, refContext);
182
183	return STOP;
184}
185
186void TextureSpecCase::renderTex (tcu::Surface& dst, deUint32 program, int width, int height)
187{
188	int		targetW		= getWidth();
189	int		targetH		= getHeight();
190
191	float	w			= (float)width	/ (float)targetW;
192	float	h			= (float)height	/ (float)targetH;
193
194	sglr::drawQuad(*getCurrentContext(), program, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(-1.0f + w*2.0f, -1.0f + h*2.0f, 0.0f));
195
196	// Read pixels back.
197	readPixels(dst, 0, 0, width, height);
198}
199
200void TextureSpecCase::readPixels (tcu::Surface& dst, int x, int y, int width, int height)
201{
202	dst.setSize(width, height);
203	glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, dst.getAccess().getDataPtr());
204}
205
206class TextureCubeArraySpecCase : public TextureSpecCase
207{
208public:
209							TextureCubeArraySpecCase	(Context& context, const char* name, const char* desc, const tcu::TextureFormat& format, int size, int depth, int numLevels);
210							~TextureCubeArraySpecCase	(void);
211
212protected:
213	virtual bool			checkExtensionSupport		(void);
214	virtual void			verifyTexture				(sglr::GLContext& gles3Context, sglr::ReferenceContext& refContext);
215
216	tcu::TextureFormat		m_texFormat;
217	tcu::TextureFormatInfo	m_texFormatInfo;
218	int						m_size;
219	int						m_depth;
220	int						m_numLevels;
221};
222
223TextureCubeArraySpecCase::TextureCubeArraySpecCase (Context& context, const char* name, const char* desc, const tcu::TextureFormat& format, int size, int depth, int numLevels)
224	: TextureSpecCase		(context, name, desc)
225	, m_texFormat			(format)
226	, m_texFormatInfo		(tcu::getTextureFormatInfo(format))
227	, m_size				(size)
228	, m_depth				(depth)
229	, m_numLevels			(numLevels)
230{
231}
232
233TextureCubeArraySpecCase::~TextureCubeArraySpecCase (void)
234{
235}
236
237bool TextureCubeArraySpecCase::checkExtensionSupport (void)
238{
239	return m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_cube_map_array");
240}
241
242void TextureCubeArraySpecCase::verifyTexture (sglr::GLContext& gles3Context, sglr::ReferenceContext& refContext)
243{
244	TextureCubeArrayShader	shader			(glu::getSamplerCubeArrayType(m_texFormat), glu::TYPE_FLOAT_VEC4);
245	deUint32				shaderIDgles	= gles3Context.createProgram(&shader);
246	deUint32				shaderIDRef		= refContext.createProgram(&shader);
247
248	shader.setTexScaleBias(m_texFormatInfo.lookupScale, m_texFormatInfo.lookupBias);
249
250	// Set state.
251	for (int ndx = 0; ndx < 2; ndx++)
252	{
253		sglr::Context* ctx = ndx ? static_cast<sglr::Context*>(&refContext) : static_cast<sglr::Context*>(&gles3Context);
254
255		setContext(ctx);
256
257		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER,	GL_NEAREST_MIPMAP_NEAREST);
258		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
259		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
260		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
261		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_R,		GL_CLAMP_TO_EDGE);
262		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAX_LEVEL,	m_numLevels-1);
263	}
264
265	for (int layerFaceNdx = 0; layerFaceNdx < m_depth; layerFaceNdx++)
266	{
267		const int			layerNdx	= layerFaceNdx / 6;
268		const tcu::CubeFace	face		= getCubeFaceFromNdx(layerFaceNdx % 6);
269		bool				layerOk		= true;
270
271		shader.setLayer(layerNdx);
272		shader.setFace(face);
273
274		for (int levelNdx = 0; levelNdx < m_numLevels; levelNdx++)
275		{
276			int				levelSize	= de::max(1, m_size	>> levelNdx);
277			tcu::Surface	reference;
278			tcu::Surface	result;
279
280			if (levelSize <= 2)
281				continue; // Fuzzy compare doesn't work for images this small.
282
283			for (int ndx = 0; ndx < 2; ndx++)
284			{
285				tcu::Surface&	dst			= ndx ? reference									: result;
286				sglr::Context*	ctx			= ndx ? static_cast<sglr::Context*>(&refContext)	: static_cast<sglr::Context*>(&gles3Context);
287				deUint32		shaderID	= ndx ? shaderIDRef									: shaderIDgles;
288
289				setContext(ctx);
290				shader.setUniforms(*ctx, shaderID);
291				renderTex(dst, shaderID, levelSize, levelSize);
292			}
293
294			const float		threshold		= 0.02f;
295			string			levelStr		= de::toString(levelNdx);
296			string			layerFaceStr	= de::toString(layerFaceNdx);
297			string			name			= string("LayerFace") + layerFaceStr + "Level" + levelStr;
298			string			desc			= string("Layer-face ") + layerFaceStr + ", Level " + levelStr;
299			bool			isFaceOk		= tcu::fuzzyCompare(m_testCtx.getLog(), name.c_str(), desc.c_str(), reference, result, threshold,
300																(levelNdx == 0 && layerFaceNdx == 0) == 0 ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
301
302			if (!isFaceOk)
303			{
304				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
305				layerOk = false;
306				break;
307			}
308		}
309
310		if (!layerOk)
311			break;
312	}
313}
314
315// Basic TexImage3D() with cube map array texture usage
316class BasicTexImageCubeArrayCase : public TextureCubeArraySpecCase
317{
318public:
319	BasicTexImageCubeArrayCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int size, int numLayers)
320		: TextureCubeArraySpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, numLayers, maxLevelCount(size))
321		, m_internalFormat			(internalFormat)
322	{
323	}
324
325protected:
326	void createTexture (void)
327	{
328		deUint32				tex			= 0;
329		tcu::TextureLevel		levelData	(m_texFormat);
330		de::Random				rnd			(deStringHash(getName()));
331		glu::TransferFormat		transferFmt	= glu::getTransferFormat(m_texFormat);
332
333		glGenTextures(1, &tex);
334		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
335		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
336
337		for (int ndx = 0; ndx < m_numLevels; ndx++)
338		{
339			int		levelW		= de::max(1, m_size	>> ndx);
340			Vec4	gMin		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
341			Vec4	gMax		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
342
343			levelData.setSize(levelW, levelW, m_depth);
344			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
345
346			glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, ndx, m_internalFormat, levelW, levelW, m_depth, 0, transferFmt.format, transferFmt.dataType, levelData.getAccess().getDataPtr());
347		}
348	}
349
350	deUint32 m_internalFormat;
351};
352
353// Basic glTexStorage3D() with cube map array texture usage
354class BasicTexStorageCubeArrayCase : public TextureCubeArraySpecCase
355{
356public:
357	BasicTexStorageCubeArrayCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int size, int numLayers, int numLevels)
358		: TextureCubeArraySpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, numLayers, numLevels)
359		, m_internalFormat			(internalFormat)
360	{
361	}
362
363protected:
364	void createTexture (void)
365	{
366		deUint32				tex			= 0;
367		tcu::TextureLevel		levelData	(m_texFormat);
368		de::Random				rnd			(deStringHash(getName()));
369		glu::TransferFormat		transferFmt	= glu::getTransferFormat(m_texFormat);
370
371		glGenTextures	(1, &tex);
372		glBindTexture	(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
373		glTexStorage3D	(GL_TEXTURE_CUBE_MAP_ARRAY, m_numLevels, m_internalFormat, m_size, m_size, m_depth);
374
375		glPixelStorei	(GL_UNPACK_ALIGNMENT, 1);
376
377		for (int ndx = 0; ndx < m_numLevels; ndx++)
378		{
379			int		levelW		= de::max(1, m_size	>> ndx);
380			Vec4	gMin		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
381			Vec4	gMax		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
382
383			levelData.setSize(levelW, levelW, m_depth);
384			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
385
386			glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, ndx, 0, 0, 0, levelW, levelW, m_depth, transferFmt.format, transferFmt.dataType, levelData.getAccess().getDataPtr());
387		}
388	}
389
390	deUint32 m_internalFormat;
391};
392
393// Pixel buffer object cases.
394
395// TexImage3D() cube map array from pixel buffer object.
396class TexImageCubeArrayBufferCase : public TextureCubeArraySpecCase
397{
398public:
399	TexImageCubeArrayBufferCase (Context&		context,
400							   const char*	name,
401							   const char*	desc,
402							   deUint32		internalFormat,
403							   int			size,
404							   int			depth,
405							   int			imageHeight,
406							   int			rowLength,
407							   int			skipImages,
408							   int			skipRows,
409							   int			skipPixels,
410							   int			alignment,
411							   int			offset)
412		: TextureCubeArraySpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, depth, 1)
413		, m_internalFormat			(internalFormat)
414		, m_imageHeight				(imageHeight)
415		, m_rowLength				(rowLength)
416		, m_skipImages				(skipImages)
417		, m_skipRows				(skipRows)
418		, m_skipPixels				(skipPixels)
419		, m_alignment				(alignment)
420		, m_offset					(offset)
421	{
422	}
423
424protected:
425	void createTexture (void)
426	{
427		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
428		int						pixelSize		= m_texFormat.getPixelSize();
429		int						rowLength		= m_rowLength > 0 ? m_rowLength : m_size;
430		int						rowPitch		= deAlign32(rowLength*pixelSize, m_alignment);
431		int						imageHeight		= m_imageHeight > 0 ? m_imageHeight : m_size;
432		int						slicePitch		= imageHeight*rowPitch;
433		deUint32				tex				= 0;
434		deUint32				buf				= 0;
435		vector<deUint8>			data;
436
437		DE_ASSERT(m_numLevels == 1);
438
439		// Fill data with grid.
440		data.resize(slicePitch*(m_depth+m_skipImages) + m_offset);
441		{
442			Vec4	cScale		= m_texFormatInfo.valueMax-m_texFormatInfo.valueMin;
443			Vec4	cBias		= m_texFormatInfo.valueMin;
444			Vec4	colorA		= Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
445			Vec4	colorB		= Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias;
446
447			tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_size, m_size, m_depth, rowPitch, slicePitch, &data[0] + m_skipImages*slicePitch + m_skipRows*rowPitch + m_skipPixels*pixelSize + m_offset), 4, colorA, colorB);
448		}
449
450		glGenBuffers(1, &buf);
451		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
452		glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
453
454		glPixelStorei(GL_UNPACK_IMAGE_HEIGHT,	m_imageHeight);
455		glPixelStorei(GL_UNPACK_ROW_LENGTH,		m_rowLength);
456		glPixelStorei(GL_UNPACK_SKIP_IMAGES,	m_skipImages);
457		glPixelStorei(GL_UNPACK_SKIP_ROWS,		m_skipRows);
458		glPixelStorei(GL_UNPACK_SKIP_PIXELS,	m_skipPixels);
459		glPixelStorei(GL_UNPACK_ALIGNMENT,		m_alignment);
460
461		glGenTextures(1, &tex);
462		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
463		glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, m_internalFormat, m_size, m_size, m_depth, 0, transferFmt.format, transferFmt.dataType, (const void*)(deUintptr)m_offset);
464	}
465
466	deUint32	m_internalFormat;
467	int			m_imageHeight;
468	int			m_rowLength;
469	int			m_skipImages;
470	int			m_skipRows;
471	int			m_skipPixels;
472	int			m_alignment;
473	int			m_offset;
474};
475
476// TexSubImage3D() cube map array PBO case.
477class TexSubImageCubeArrayBufferCase : public TextureCubeArraySpecCase
478{
479public:
480	TexSubImageCubeArrayBufferCase (Context&		context,
481								 const char*	name,
482								 const char*	desc,
483								 deUint32		internalFormat,
484								 int			size,
485								 int			depth,
486								 int			subX,
487								 int			subY,
488								 int			subZ,
489								 int			subW,
490								 int			subH,
491								 int			subD,
492								 int			imageHeight,
493								 int			rowLength,
494								 int			skipImages,
495								 int			skipRows,
496								 int			skipPixels,
497								 int			alignment,
498								 int			offset)
499		: TextureCubeArraySpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, depth, 1)
500		, m_internalFormat			(internalFormat)
501		, m_subX					(subX)
502		, m_subY					(subY)
503		, m_subZ					(subZ)
504		, m_subW					(subW)
505		, m_subH					(subH)
506		, m_subD					(subD)
507		, m_imageHeight				(imageHeight)
508		, m_rowLength				(rowLength)
509		, m_skipImages				(skipImages)
510		, m_skipRows				(skipRows)
511		, m_skipPixels				(skipPixels)
512		, m_alignment				(alignment)
513		, m_offset					(offset)
514	{
515	}
516
517protected:
518	void createTexture (void)
519	{
520		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
521		int						pixelSize		= m_texFormat.getPixelSize();
522		deUint32				tex				= 0;
523		deUint32				buf				= 0;
524		vector<deUint8>			data;
525
526		DE_ASSERT(m_numLevels == 1);
527
528		glGenTextures(1, &tex);
529		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
530
531		// Fill with gradient.
532		{
533			int		rowPitch		= deAlign32(pixelSize*m_size,  4);
534			int		slicePitch		= rowPitch*m_size;
535
536			data.resize(slicePitch*m_depth);
537			tcu::fillWithComponentGradients(tcu::PixelBufferAccess(m_texFormat, m_size, m_size, m_depth, rowPitch, slicePitch, &data[0]), m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
538		}
539
540		glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, m_internalFormat, m_size, m_size, m_depth, 0, transferFmt.format, transferFmt.dataType, &data[0]);
541
542		// Fill data with grid.
543		{
544			int		rowLength		= m_rowLength > 0 ? m_rowLength : m_subW;
545			int		rowPitch		= deAlign32(rowLength*pixelSize, m_alignment);
546			int		imageHeight		= m_imageHeight > 0 ? m_imageHeight : m_subH;
547			int		slicePitch		= imageHeight*rowPitch;
548			Vec4	cScale			= m_texFormatInfo.valueMax-m_texFormatInfo.valueMin;
549			Vec4	cBias			= m_texFormatInfo.valueMin;
550			Vec4	colorA			= Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
551			Vec4	colorB			= Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias;
552
553			data.resize(slicePitch*(m_depth+m_skipImages) + m_offset);
554			tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_subW, m_subH, m_subD, rowPitch, slicePitch, &data[0] + m_skipImages*slicePitch + m_skipRows*rowPitch + m_skipPixels*pixelSize + m_offset), 4, colorA, colorB);
555		}
556
557		glGenBuffers(1, &buf);
558		glBindBuffer(GL_PIXEL_UNPACK_BUFFER,	buf);
559		glBufferData(GL_PIXEL_UNPACK_BUFFER,	(int)data.size(), &data[0], GL_STATIC_DRAW);
560
561		glPixelStorei(GL_UNPACK_IMAGE_HEIGHT,	m_imageHeight);
562		glPixelStorei(GL_UNPACK_ROW_LENGTH,		m_rowLength);
563		glPixelStorei(GL_UNPACK_SKIP_IMAGES,	m_skipImages);
564		glPixelStorei(GL_UNPACK_SKIP_ROWS,		m_skipRows);
565		glPixelStorei(GL_UNPACK_SKIP_PIXELS,	m_skipPixels);
566		glPixelStorei(GL_UNPACK_ALIGNMENT,		m_alignment);
567		glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, m_subX, m_subY, m_subZ, m_subW, m_subH, m_subD, transferFmt.format, transferFmt.dataType, (const void*)(deIntptr)m_offset);
568	}
569
570	deUint32	m_internalFormat;
571	int			m_subX;
572	int			m_subY;
573	int			m_subZ;
574	int			m_subW;
575	int			m_subH;
576	int			m_subD;
577	int			m_imageHeight;
578	int			m_rowLength;
579	int			m_skipImages;
580	int			m_skipRows;
581	int			m_skipPixels;
582	int			m_alignment;
583	int			m_offset;
584};
585
586// TexImage3D() depth case.
587class TexImageCubeArrayDepthCase : public TextureCubeArraySpecCase
588{
589public:
590	TexImageCubeArrayDepthCase (Context&	context,
591							  const char*	name,
592							  const char*	desc,
593							  deUint32		internalFormat,
594							  int			imageSize,
595							  int			numLayers)
596		: TextureCubeArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageSize, numLayers, maxLevelCount(imageSize))
597		, m_internalFormat		(internalFormat)
598	{
599		// we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
600		m_texFormatInfo.lookupBias = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
601		m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
602	}
603
604	void createTexture (void)
605	{
606		glu::TransferFormat	fmt			= glu::getTransferFormat(m_texFormat);
607		deUint32			tex			= 0;
608		tcu::TextureLevel	levelData	(m_texFormat);
609
610		glGenTextures(1, &tex);
611		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
612		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
613		GLU_CHECK();
614
615		for (int ndx = 0; ndx < m_numLevels; ndx++)
616		{
617			const int   levelW		= de::max(1, m_size >> ndx);
618			const Vec4  gMin		= Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
619			const Vec4  gMax		= Vec4(2.0f, 1.5f, -1.0f, 2.0f);
620
621			levelData.setSize(levelW, levelW, m_depth);
622			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
623
624			glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, ndx, m_internalFormat, levelW, levelW, m_depth, 0, fmt.format, fmt.dataType, levelData.getAccess().getDataPtr());
625		}
626	}
627
628	const deUint32 m_internalFormat;
629};
630
631// TexSubImage3D() depth case.
632class TexSubImageCubeArrayDepthCase : public TextureCubeArraySpecCase
633{
634public:
635	TexSubImageCubeArrayDepthCase (Context&		context,
636								 const char*	name,
637								 const char*	desc,
638								 deUint32		internalFormat,
639								 int			imageSize,
640								 int			numLayers)
641		: TextureCubeArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageSize, numLayers, maxLevelCount(imageSize))
642		, m_internalFormat		(internalFormat)
643	{
644		// we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
645		m_texFormatInfo.lookupBias = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
646		m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
647	}
648
649	void createTexture (void)
650	{
651		glu::TransferFormat	fmt			= glu::getTransferFormat(m_texFormat);
652		de::Random			rnd			(deStringHash(getName()));
653		deUint32			tex			= 0;
654		tcu::TextureLevel	levelData	(m_texFormat);
655
656		glGenTextures(1, &tex);
657		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
658		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
659		GLU_CHECK();
660
661		// First specify full texture.
662		for (int ndx = 0; ndx < m_numLevels; ndx++)
663		{
664			const int   levelW		= de::max(1, m_size >> ndx);
665			const Vec4  gMin		= Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
666			const Vec4  gMax		= Vec4(2.0f, 1.5f, -1.0f, 2.0f);
667
668			levelData.setSize(levelW, levelW, m_depth);
669			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
670
671			glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, ndx, m_internalFormat, levelW, levelW, m_depth, 0, fmt.format, fmt.dataType, levelData.getAccess().getDataPtr());
672		}
673
674		// Re-specify parts of each level.
675		for (int ndx = 0; ndx < m_numLevels; ndx++)
676		{
677			const int	levelW		= de::max(1, m_size >> ndx);
678
679			const int	w			= rnd.getInt(1, levelW);
680			const int	h			= rnd.getInt(1, levelW);
681			const int	d			= rnd.getInt(1, m_depth);
682			const int	x			= rnd.getInt(0, levelW-w);
683			const int	y			= rnd.getInt(0, levelW-h);
684			const int	z			= rnd.getInt(0, m_depth-d);
685
686			const Vec4	colorA		= Vec4(2.0f, 1.5f, -1.0f, 2.0f);
687			const Vec4	colorB		= Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
688			const int	cellSize	= rnd.getInt(2, 16);
689
690			levelData.setSize(w, h, d);
691			tcu::fillWithGrid(levelData.getAccess(), cellSize, colorA, colorB);
692
693			glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, ndx, x, y, z, w, h, d, fmt.format, fmt.dataType, levelData.getAccess().getDataPtr());
694		}
695	}
696
697	const deUint32 m_internalFormat;
698};
699
700// TexImage3D() depth case with pbo.
701class TexImageCubeArrayDepthBufferCase : public TextureCubeArraySpecCase
702{
703public:
704	TexImageCubeArrayDepthBufferCase (Context&	context,
705									const char*	name,
706									const char*	desc,
707									deUint32	internalFormat,
708									int			imageSize,
709									int			numLayers)
710		: TextureCubeArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageSize, numLayers, 1)
711		, m_internalFormat		(internalFormat)
712	{
713		// we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
714		m_texFormatInfo.lookupBias = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
715		m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
716	}
717
718	void createTexture (void)
719	{
720		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
721		int						pixelSize		= m_texFormat.getPixelSize();
722		int						rowLength		= m_size;
723		int						alignment		= 4;
724		int						rowPitch		= deAlign32(rowLength*pixelSize, alignment);
725		int						imageHeight		= m_size;
726		int						slicePitch		= imageHeight*rowPitch;
727		deUint32				tex				= 0;
728		deUint32				buf				= 0;
729		vector<deUint8>			data;
730
731		DE_ASSERT(m_numLevels == 1);
732
733		// Fill data with grid.
734		data.resize(slicePitch*m_depth);
735		{
736			const Vec4 gMin = Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
737			const Vec4 gMax = Vec4(2.0f, 1.5f, -1.0f, 2.0f);
738
739			tcu::fillWithComponentGradients(tcu::PixelBufferAccess(m_texFormat, m_size, m_size, m_depth, rowPitch, slicePitch, &data[0]), gMin, gMax);
740		}
741
742		glGenBuffers(1, &buf);
743		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
744		glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
745
746		glPixelStorei(GL_UNPACK_IMAGE_HEIGHT,	imageHeight);
747		glPixelStorei(GL_UNPACK_ROW_LENGTH,		rowLength);
748		glPixelStorei(GL_UNPACK_SKIP_IMAGES,	0);
749		glPixelStorei(GL_UNPACK_SKIP_ROWS,		0);
750		glPixelStorei(GL_UNPACK_SKIP_PIXELS,	0);
751		glPixelStorei(GL_UNPACK_ALIGNMENT,		alignment);
752
753		glGenTextures(1, &tex);
754		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
755		glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, m_internalFormat, m_size, m_size, m_depth, 0, transferFmt.format, transferFmt.dataType, DE_NULL);
756		glDeleteBuffers(1, &buf);
757	}
758
759	const deUint32 m_internalFormat;
760};
761
762TextureSpecificationTests::TextureSpecificationTests (Context& context)
763	: TestCaseGroup(context, "specification", "Texture Specification Tests")
764{
765}
766
767TextureSpecificationTests::~TextureSpecificationTests (void)
768{
769}
770
771void TextureSpecificationTests::init (void)
772{
773	struct
774	{
775		const char*	name;
776		deUint32	internalFormat;
777	} colorFormats[] =
778	{
779		{ "rgba32f",			GL_RGBA32F,			},
780		{ "rgba32i",			GL_RGBA32I,			},
781		{ "rgba32ui",			GL_RGBA32UI,		},
782		{ "rgba16f",			GL_RGBA16F,			},
783		{ "rgba16i",			GL_RGBA16I,			},
784		{ "rgba16ui",			GL_RGBA16UI,		},
785		{ "rgba8",				GL_RGBA8,			},
786		{ "rgba8i",				GL_RGBA8I,			},
787		{ "rgba8ui",			GL_RGBA8UI,			},
788		{ "srgb8_alpha8",		GL_SRGB8_ALPHA8,	},
789		{ "rgb10_a2",			GL_RGB10_A2,		},
790		{ "rgb10_a2ui",			GL_RGB10_A2UI,		},
791		{ "rgba4",				GL_RGBA4,			},
792		{ "rgb5_a1",			GL_RGB5_A1,			},
793		{ "rgba8_snorm",		GL_RGBA8_SNORM,		},
794		{ "rgb8",				GL_RGB8,			},
795		{ "rgb565",				GL_RGB565,			},
796		{ "r11f_g11f_b10f",		GL_R11F_G11F_B10F,	},
797		{ "rgb32f",				GL_RGB32F,			},
798		{ "rgb32i",				GL_RGB32I,			},
799		{ "rgb32ui",			GL_RGB32UI,			},
800		{ "rgb16f",				GL_RGB16F,			},
801		{ "rgb16i",				GL_RGB16I,			},
802		{ "rgb16ui",			GL_RGB16UI,			},
803		{ "rgb8_snorm",			GL_RGB8_SNORM,		},
804		{ "rgb8i",				GL_RGB8I,			},
805		{ "rgb8ui",				GL_RGB8UI,			},
806		{ "srgb8",				GL_SRGB8,			},
807		{ "rgb9_e5",			GL_RGB9_E5,			},
808		{ "rg32f",				GL_RG32F,			},
809		{ "rg32i",				GL_RG32I,			},
810		{ "rg32ui",				GL_RG32UI,			},
811		{ "rg16f",				GL_RG16F,			},
812		{ "rg16i",				GL_RG16I,			},
813		{ "rg16ui",				GL_RG16UI,			},
814		{ "rg8",				GL_RG8,				},
815		{ "rg8i",				GL_RG8I,			},
816		{ "rg8ui",				GL_RG8UI,			},
817		{ "rg8_snorm",			GL_RG8_SNORM,		},
818		{ "r32f",				GL_R32F,			},
819		{ "r32i",				GL_R32I,			},
820		{ "r32ui",				GL_R32UI,			},
821		{ "r16f",				GL_R16F,			},
822		{ "r16i",				GL_R16I,			},
823		{ "r16ui",				GL_R16UI,			},
824		{ "r8",					GL_R8,				},
825		{ "r8i",				GL_R8I,				},
826		{ "r8ui",				GL_R8UI,			},
827		{ "r8_snorm",			GL_R8_SNORM,		}
828	};
829
830	static const struct
831	{
832		const char*	name;
833		deUint32	internalFormat;
834	} depthStencilFormats[] =
835	{
836		// Depth and stencil formats
837		{ "depth_component32f",	GL_DEPTH_COMPONENT32F	},
838		{ "depth_component24",	GL_DEPTH_COMPONENT24	},
839		{ "depth_component16",	GL_DEPTH_COMPONENT16	},
840		{ "depth32f_stencil8",	GL_DEPTH32F_STENCIL8	},
841		{ "depth24_stencil8",	GL_DEPTH24_STENCIL8		}
842	};
843
844	// Basic TexImage3D usage.
845	{
846		tcu::TestCaseGroup* basicTexImageGroup = new tcu::TestCaseGroup(m_testCtx, "basic_teximage3d", "Basic glTexImage3D() usage");
847		addChild(basicTexImageGroup);
848		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
849		{
850			const char*	fmtName				= colorFormats[formatNdx].name;
851			deUint32	format				= colorFormats[formatNdx].internalFormat;
852			const int	texCubeArraySize	= 64;
853			const int	texCubeArrayLayers	= 6;
854
855			basicTexImageGroup->addChild(new BasicTexImageCubeArrayCase	(m_context,	(string(fmtName) + "_cube_array").c_str(),	"",	format, texCubeArraySize, texCubeArrayLayers));
856		}
857	}
858
859	// glTexImage3D() pbo cases.
860	{
861		tcu::TestCaseGroup* pboGroup = new tcu::TestCaseGroup(m_testCtx, "teximage3d_pbo", "glTexImage3D() from PBO");
862		addChild(pboGroup);
863
864		// Parameter cases
865		static const struct
866		{
867			const char*	name;
868			deUint32	format;
869			int			size;
870			int			depth;
871			int			imageHeight;
872			int			rowLength;
873			int			skipImages;
874			int			skipRows;
875			int			skipPixels;
876			int			alignment;
877			int			offset;
878		} parameterCases[] =
879		{
880			{ "rgb8_offset",		GL_RGB8,	23,	6,	0,	0,	0,	0,	0,	1,	67 },
881			{ "rgb8_alignment",		GL_RGB8,	23,	6,	0,	0,	0,	0,	0,	2,	0 },
882			{ "rgb8_image_height",	GL_RGB8,	23,	6,	26,	0,	0,	0,	0,	4,	0 },
883			{ "rgb8_row_length",	GL_RGB8,	23,	6,	0,	27,	0,	0,	0,	4,	0 },
884			{ "rgb8_skip_images",	GL_RGB8,	23,	6,	0,	0,	3,	0,	0,	4,	0 },
885			{ "rgb8_skip_rows",		GL_RGB8,	23,	6,	26,	0,	0,	3,	0,	4,	0 },
886			{ "rgb8_skip_pixels",	GL_RGB8,	23,	6,	0,	25,	0,	0,	2,	4,	0 }
887		};
888
889		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
890		{
891			const string	fmtName				= colorFormats[formatNdx].name;
892			const deUint32	format				= colorFormats[formatNdx].internalFormat;
893			const int		texCubeArraySize	= 20;
894			const int		texCubeDepth		= 6;
895
896			pboGroup->addChild(new TexImageCubeArrayBufferCase	(m_context, (fmtName + "_cube_array").c_str(),	"", format, texCubeArraySize, texCubeDepth, 0, 0, 0, 0, 0, 4, 0));
897		}
898
899		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(parameterCases); ndx++)
900		{
901			pboGroup->addChild(new TexImageCubeArrayBufferCase(m_context, (string(parameterCases[ndx].name) + "_cube_array").c_str(), "",
902														parameterCases[ndx].format,
903														parameterCases[ndx].size,
904														parameterCases[ndx].depth,
905														parameterCases[ndx].imageHeight,
906														parameterCases[ndx].rowLength,
907														parameterCases[ndx].skipImages,
908														parameterCases[ndx].skipRows,
909														parameterCases[ndx].skipPixels,
910														parameterCases[ndx].alignment,
911														parameterCases[ndx].offset));
912		}
913	}
914
915	// glTexImage3D() depth cases.
916	{
917		tcu::TestCaseGroup* shadow3dGroup = new tcu::TestCaseGroup(m_testCtx, "teximage3d_depth", "glTexImage3D() with depth or depth/stencil format");
918		addChild(shadow3dGroup);
919
920		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
921		{
922			const int	texCubeArraySize	= 64;
923			const int	texCubeArrayDepth	= 6;
924
925			shadow3dGroup->addChild(new TexImageCubeArrayDepthCase(m_context, (std::string(depthStencilFormats[ndx].name) + "_cube_array").c_str(), "", depthStencilFormats[ndx].internalFormat, texCubeArraySize, texCubeArrayDepth));
926		}
927	}
928
929	// glTexImage3D() depth cases with pbo.
930	{
931		tcu::TestCaseGroup* shadow3dGroup = new tcu::TestCaseGroup(m_testCtx, "teximage3d_depth_pbo", "glTexImage3D() with depth or depth/stencil format with pbo");
932		addChild(shadow3dGroup);
933
934		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
935		{
936			const int	texCubeArraySize	= 64;
937			const int	texCubeArrayDepth	= 6;
938
939			shadow3dGroup->addChild(new TexImageCubeArrayDepthBufferCase(m_context, (std::string(depthStencilFormats[ndx].name) + "_cube_array").c_str(), "", depthStencilFormats[ndx].internalFormat, texCubeArraySize, texCubeArrayDepth));
940		}
941	}
942
943	// glTexSubImage3D() PBO cases.
944	{
945		tcu::TestCaseGroup* pboGroup = new tcu::TestCaseGroup(m_testCtx, "texsubimage3d_pbo", "glTexSubImage3D() pixel buffer object tests");
946		addChild(pboGroup);
947
948		static const struct
949		{
950			const char*	name;
951			deUint32	format;
952			int			size;
953			int			depth;
954			int			subX;
955			int			subY;
956			int			subZ;
957			int			subW;
958			int			subH;
959			int			subD;
960			int			imageHeight;
961			int			rowLength;
962			int			skipImages;
963			int			skipRows;
964			int			skipPixels;
965			int			alignment;
966			int			offset;
967		} paramCases[] =
968		{
969			{ "rgb8_offset",		GL_RGB8,	26, 12,	1,	2,	1,	23,	19,	8,	0,	0,	0,	0,	0,	4,	67 },
970			{ "rgb8_image_height",	GL_RGB8,	26, 12,	1,	2,	1,	23,	19,	8,	26,	0,	0,	0,	0,	4,	0 },
971			{ "rgb8_row_length",	GL_RGB8,	26, 12,	1,	2,	1,	23,	19,	8,	0,	27,	0,	0,	0,	4,	0 },
972			{ "rgb8_skip_images",	GL_RGB8,	26, 12,	1,	2,	1,	23,	19,	8,	0,	0,	3,	0,	0,	4,	0 },
973			{ "rgb8_skip_rows",		GL_RGB8,	26, 12,	1,	2,	1,	23,	19,	8,	22,	0,	0,	3,	0,	4,	0 },
974			{ "rgb8_skip_pixels",	GL_RGB8,	26, 12,	1,	2,	1,	23,	19,	8,	0,	25,	0,	0,	2,	4,	0 }
975		};
976
977		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++)
978		{
979			pboGroup->addChild(new TexSubImageCubeArrayBufferCase(m_context, (std::string(colorFormats[ndx].name) + "_cube_array").c_str(), "",
980														   colorFormats[ndx].internalFormat,
981														   26,	// Size
982														   12,	// Depth
983														   1,	// Sub X
984														   2,	// Sub Y
985														   0,	// Sub Z
986														   23,	// Sub W
987														   19,	// Sub H
988														   8,	// Sub D
989														   0,	// Image height
990														   0,	// Row length
991														   0,	// Skip images
992														   0,	// Skip rows
993														   0,	// Skip pixels
994														   4,	// Alignment
995														   0	/* offset */));
996		}
997
998		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(paramCases); ndx++)
999		{
1000			pboGroup->addChild(new TexSubImageCubeArrayBufferCase(m_context, (std::string(paramCases[ndx].name) + "_cube_array").c_str(), "",
1001														   paramCases[ndx].format,
1002														   paramCases[ndx].size,
1003														   paramCases[ndx].depth,
1004														   paramCases[ndx].subX,
1005														   paramCases[ndx].subY,
1006														   paramCases[ndx].subZ,
1007														   paramCases[ndx].subW,
1008														   paramCases[ndx].subH,
1009														   paramCases[ndx].subD,
1010														   paramCases[ndx].imageHeight,
1011														   paramCases[ndx].rowLength,
1012														   paramCases[ndx].skipImages,
1013														   paramCases[ndx].skipRows,
1014														   paramCases[ndx].skipPixels,
1015														   paramCases[ndx].alignment,
1016														   paramCases[ndx].offset));
1017		}
1018	}
1019
1020	// glTexSubImage3D() depth cases.
1021	{
1022		tcu::TestCaseGroup* shadow3dGroup = new tcu::TestCaseGroup(m_testCtx, "texsubimage3d_depth", "glTexSubImage3D() with depth or depth/stencil format");
1023		addChild(shadow3dGroup);
1024
1025		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
1026		{
1027			const int	texCubeArraySize	= 57;
1028			const int	texCubeArrayLayers	= 6;
1029
1030			shadow3dGroup->addChild(new TexSubImageCubeArrayDepthCase(m_context, (std::string(depthStencilFormats[ndx].name) + "_cube_array").c_str(), "", depthStencilFormats[ndx].internalFormat, texCubeArraySize, texCubeArrayLayers));
1031		}
1032	}
1033
1034	// glTexStorage3D() cases.
1035	{
1036		tcu::TestCaseGroup* texStorageGroup = new tcu::TestCaseGroup(m_testCtx, "texstorage3d", "Basic glTexStorage3D() usage");
1037		addChild(texStorageGroup);
1038
1039		// All formats.
1040		tcu::TestCaseGroup* formatGroup = new tcu::TestCaseGroup(m_testCtx, "format", "glTexStorage3D() with all formats");
1041		texStorageGroup->addChild(formatGroup);
1042
1043		// Color formats.
1044		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
1045		{
1046			const char*	fmtName				= colorFormats[formatNdx].name;
1047			deUint32	internalFormat		= colorFormats[formatNdx].internalFormat;
1048			const int	texCubeArraySize	= 57;
1049			const int	texCubeArrayLayers	= 6;
1050			int			texCubeArrayLevels	= maxLevelCount(texCubeArraySize);
1051
1052			formatGroup->addChild(new BasicTexStorageCubeArrayCase	(m_context, (string(fmtName) + "_cube_array").c_str(),	"", internalFormat, texCubeArraySize, texCubeArrayLayers, texCubeArrayLevels));
1053		}
1054
1055		// Depth/stencil formats (only 2D texture array is supported).
1056		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); formatNdx++)
1057		{
1058			const char*	fmtName				= depthStencilFormats[formatNdx].name;
1059			deUint32	internalFormat		= depthStencilFormats[formatNdx].internalFormat;
1060			const int	texCubeArraySize	= 57;
1061			const int	texCubeArrayLayers	= 6;
1062			int			texCubeArrayLevels	= maxLevelCount(texCubeArraySize);
1063
1064			formatGroup->addChild(new BasicTexStorageCubeArrayCase	(m_context, (string(fmtName) + "_cube_array").c_str(),	"", internalFormat, texCubeArraySize, texCubeArrayLayers, texCubeArrayLevels));
1065		}
1066
1067		// Sizes.
1068		static const struct
1069		{
1070			int				size;
1071			int				layers;
1072			int				levels;
1073		} texCubeArraySizes[] =
1074		{
1075			//	Sz	La	Le
1076			{	1,	6,	1 },
1077			{	2,	6,	2 },
1078			{	32,	6,	3 },
1079			{	64,	6,	4 },
1080			{	57,	12,	1 },
1081			{	57,	12,	2 },
1082			{	57,	12,	6 }
1083		};
1084
1085		tcu::TestCaseGroup* sizeGroup = new tcu::TestCaseGroup(m_testCtx, "size", "glTexStorage3D() with various sizes");
1086		texStorageGroup->addChild(sizeGroup);
1087
1088		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(texCubeArraySizes); ndx++)
1089		{
1090			const deUint32		format		= GL_RGBA8;
1091			int					size		= texCubeArraySizes[ndx].size;
1092			int					layers		= texCubeArraySizes[ndx].layers;
1093			int					levels		= texCubeArraySizes[ndx].levels;
1094			string				name		= string("cube_array_") + de::toString(size) + "x" + de::toString(size) + "x" + de::toString(layers) + "_" + de::toString(levels) + "_levels";
1095
1096			sizeGroup->addChild(new BasicTexStorageCubeArrayCase(m_context, name.c_str(), "", format, size, layers, levels));
1097		}
1098	}
1099}
1100
1101} // Functional
1102} // gles3
1103} // deqp
1104