Home | History | Annotate | Download | only in functional
      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 
     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 
     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:
    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 
    125 TextureSpecCase::TextureSpecCase (Context& context, const char* name, const char* desc)
    126 	: TestCase(context, name, desc)
    127 {
    128 }
    129 
    130 TextureSpecCase::~TextureSpecCase (void)
    131 {
    132 }
    133 
    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 
    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 
    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 
    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 
    233 TextureCubeArraySpecCase::~TextureCubeArraySpecCase (void)
    234 {
    235 }
    236 
    237 bool TextureCubeArraySpecCase::checkExtensionSupport (void)
    238 {
    239 	return m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_cube_map_array");
    240 }
    241 
    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:
    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:
    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:
    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:
    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:
    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:
    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:
    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:
    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:
    590 	TexImageCubeArrayDepthCase (Context&	context,
    591 							  const char*	name,
    592 							  const char*	desc,
    593 							  deUint32		internalFormat,
    594 							  int			imageSize,
    595 							  int			numLayers)
    596 		: TextureCubeArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageSize, numLayers, maxLevelCount(imageSize))
    597 		, m_internalFormat		(internalFormat)
    598 	{
    599 		// we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
    600 		m_texFormatInfo.lookupBias = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
    601 		m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
    602 	}
    603 
    604 	void createTexture (void)
    605 	{
    606 		glu::TransferFormat	fmt			= glu::getTransferFormat(m_texFormat);
    607 		deUint32			tex			= 0;
    608 		tcu::TextureLevel	levelData	(m_texFormat);
    609 
    610 		glGenTextures(1, &tex);
    611 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
    612 		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    613 		GLU_CHECK();
    614 
    615 		for (int ndx = 0; ndx < m_numLevels; ndx++)
    616 		{
    617 			const int   levelW		= de::max(1, m_size >> ndx);
    618 			const Vec4  gMin		= Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
    619 			const Vec4  gMax		= Vec4(2.0f, 1.5f, -1.0f, 2.0f);
    620 
    621 			levelData.setSize(levelW, levelW, m_depth);
    622 			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
    623 
    624 			glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, ndx, m_internalFormat, levelW, levelW, m_depth, 0, fmt.format, fmt.dataType, levelData.getAccess().getDataPtr());
    625 		}
    626 	}
    627 
    628 	const deUint32 m_internalFormat;
    629 };
    630 
    631 // TexSubImage3D() depth case.
    632 class TexSubImageCubeArrayDepthCase : public TextureCubeArraySpecCase
    633 {
    634 public:
    635 	TexSubImageCubeArrayDepthCase (Context&		context,
    636 								 const char*	name,
    637 								 const char*	desc,
    638 								 deUint32		internalFormat,
    639 								 int			imageSize,
    640 								 int			numLayers)
    641 		: TextureCubeArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageSize, numLayers, maxLevelCount(imageSize))
    642 		, m_internalFormat		(internalFormat)
    643 	{
    644 		// we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
    645 		m_texFormatInfo.lookupBias = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
    646 		m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
    647 	}
    648 
    649 	void createTexture (void)
    650 	{
    651 		glu::TransferFormat	fmt			= glu::getTransferFormat(m_texFormat);
    652 		de::Random			rnd			(deStringHash(getName()));
    653 		deUint32			tex			= 0;
    654 		tcu::TextureLevel	levelData	(m_texFormat);
    655 
    656 		glGenTextures(1, &tex);
    657 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
    658 		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    659 		GLU_CHECK();
    660 
    661 		// First specify full texture.
    662 		for (int ndx = 0; ndx < m_numLevels; ndx++)
    663 		{
    664 			const int   levelW		= de::max(1, m_size >> ndx);
    665 			const Vec4  gMin		= Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
    666 			const Vec4  gMax		= Vec4(2.0f, 1.5f, -1.0f, 2.0f);
    667 
    668 			levelData.setSize(levelW, levelW, m_depth);
    669 			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
    670 
    671 			glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, ndx, m_internalFormat, levelW, levelW, m_depth, 0, fmt.format, fmt.dataType, levelData.getAccess().getDataPtr());
    672 		}
    673 
    674 		// Re-specify parts of each level.
    675 		for (int ndx = 0; ndx < m_numLevels; ndx++)
    676 		{
    677 			const int	levelW		= de::max(1, m_size >> ndx);
    678 
    679 			const int	w			= rnd.getInt(1, levelW);
    680 			const int	h			= rnd.getInt(1, levelW);
    681 			const int	d			= rnd.getInt(1, m_depth);
    682 			const int	x			= rnd.getInt(0, levelW-w);
    683 			const int	y			= rnd.getInt(0, levelW-h);
    684 			const int	z			= rnd.getInt(0, m_depth-d);
    685 
    686 			const Vec4	colorA		= Vec4(2.0f, 1.5f, -1.0f, 2.0f);
    687 			const Vec4	colorB		= Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
    688 			const int	cellSize	= rnd.getInt(2, 16);
    689 
    690 			levelData.setSize(w, h, d);
    691 			tcu::fillWithGrid(levelData.getAccess(), cellSize, colorA, colorB);
    692 
    693 			glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, ndx, x, y, z, w, h, d, fmt.format, fmt.dataType, levelData.getAccess().getDataPtr());
    694 		}
    695 	}
    696 
    697 	const deUint32 m_internalFormat;
    698 };
    699 
    700 // TexImage3D() depth case with pbo.
    701 class TexImageCubeArrayDepthBufferCase : public TextureCubeArraySpecCase
    702 {
    703 public:
    704 	TexImageCubeArrayDepthBufferCase (Context&	context,
    705 									const char*	name,
    706 									const char*	desc,
    707 									deUint32	internalFormat,
    708 									int			imageSize,
    709 									int			numLayers)
    710 		: TextureCubeArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageSize, numLayers, 1)
    711 		, m_internalFormat		(internalFormat)
    712 	{
    713 		// we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
    714 		m_texFormatInfo.lookupBias = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
    715 		m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
    716 	}
    717 
    718 	void createTexture (void)
    719 	{
    720 		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
    721 		int						pixelSize		= m_texFormat.getPixelSize();
    722 		int						rowLength		= m_size;
    723 		int						alignment		= 4;
    724 		int						rowPitch		= deAlign32(rowLength*pixelSize, alignment);
    725 		int						imageHeight		= m_size;
    726 		int						slicePitch		= imageHeight*rowPitch;
    727 		deUint32				tex				= 0;
    728 		deUint32				buf				= 0;
    729 		vector<deUint8>			data;
    730 
    731 		DE_ASSERT(m_numLevels == 1);
    732 
    733 		// Fill data with grid.
    734 		data.resize(slicePitch*m_depth);
    735 		{
    736 			const Vec4 gMin = Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
    737 			const Vec4 gMax = Vec4(2.0f, 1.5f, -1.0f, 2.0f);
    738 
    739 			tcu::fillWithComponentGradients(tcu::PixelBufferAccess(m_texFormat, m_size, m_size, m_depth, rowPitch, slicePitch, &data[0]), gMin, gMax);
    740 		}
    741 
    742 		glGenBuffers(1, &buf);
    743 		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
    744 		glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
    745 
    746 		glPixelStorei(GL_UNPACK_IMAGE_HEIGHT,	imageHeight);
    747 		glPixelStorei(GL_UNPACK_ROW_LENGTH,		rowLength);
    748 		glPixelStorei(GL_UNPACK_SKIP_IMAGES,	0);
    749 		glPixelStorei(GL_UNPACK_SKIP_ROWS,		0);
    750 		glPixelStorei(GL_UNPACK_SKIP_PIXELS,	0);
    751 		glPixelStorei(GL_UNPACK_ALIGNMENT,		alignment);
    752 
    753 		glGenTextures(1, &tex);
    754 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
    755 		glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, m_internalFormat, m_size, m_size, m_depth, 0, transferFmt.format, transferFmt.dataType, DE_NULL);
    756 		glDeleteBuffers(1, &buf);
    757 	}
    758 
    759 	const deUint32 m_internalFormat;
    760 };
    761 
    762 TextureSpecificationTests::TextureSpecificationTests (Context& context)
    763 	: TestCaseGroup(context, "specification", "Texture Specification Tests")
    764 {
    765 }
    766 
    767 TextureSpecificationTests::~TextureSpecificationTests (void)
    768 {
    769 }
    770 
    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