• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	return m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_cube_map_array");
240 }
241 
verifyTexture(sglr::GLContext & gles3Context,sglr::ReferenceContext & refContext)242 void 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
316 class BasicTexImageCubeArrayCase : public TextureCubeArraySpecCase
317 {
318 public:
BasicTexImageCubeArrayCase(Context & context,const char * name,const char * desc,deUint32 internalFormat,int size,int numLayers)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 
325 protected:
createTexture(void)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
354 class BasicTexStorageCubeArrayCase : public TextureCubeArraySpecCase
355 {
356 public:
BasicTexStorageCubeArrayCase(Context & context,const char * name,const char * desc,deUint32 internalFormat,int size,int numLayers,int numLevels)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 
363 protected:
createTexture(void)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.
396 class TexImageCubeArrayBufferCase : public TextureCubeArraySpecCase
397 {
398 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)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 
424 protected:
createTexture(void)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.
477 class TexSubImageCubeArrayBufferCase : public TextureCubeArraySpecCase
478 {
479 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)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 
517 protected:
createTexture(void)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.
587 class TexImageCubeArrayDepthCase : public TextureCubeArraySpecCase
588 {
589 public:
TexImageCubeArrayDepthCase(Context & context,const char * name,const char * desc,deUint32 internalFormat,int imageSize,int numLayers)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 
createTexture(void)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.
632 class TexSubImageCubeArrayDepthCase : public TextureCubeArraySpecCase
633 {
634 public:
TexSubImageCubeArrayDepthCase(Context & context,const char * name,const char * desc,deUint32 internalFormat,int imageSize,int numLayers)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 
createTexture(void)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.
701 class TexImageCubeArrayDepthBufferCase : public TextureCubeArraySpecCase
702 {
703 public:
TexImageCubeArrayDepthBufferCase(Context & context,const char * name,const char * desc,deUint32 internalFormat,int imageSize,int numLayers)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 
createTexture(void)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 
TextureSpecificationTests(Context & context)762 TextureSpecificationTests::TextureSpecificationTests (Context& context)
763 	: TestCaseGroup(context, "specification", "Texture Specification Tests")
764 {
765 }
766 
~TextureSpecificationTests(void)767 TextureSpecificationTests::~TextureSpecificationTests (void)
768 {
769 }
770 
init(void)771 void 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