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