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