es3fTextureSpecificationTests.cpp revision 5a0a3bbda9383ed89e44198619b9564282905865
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 "es3fTextureSpecificationTests.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 "es3fFboTestUtil.hpp"
47
48#include "glwEnums.hpp"
49
50namespace deqp
51{
52namespace gles3
53{
54namespace Functional
55{
56
57using std::string;
58using std::vector;
59using std::pair;
60using tcu::TestLog;
61using tcu::Vec4;
62using tcu::IVec4;
63using tcu::UVec4;
64using namespace FboTestUtil;
65
66tcu::TextureFormat mapGLUnsizedInternalFormat (deUint32 internalFormat)
67{
68	using tcu::TextureFormat;
69	switch (internalFormat)
70	{
71		case GL_ALPHA:				return TextureFormat(TextureFormat::A,		TextureFormat::UNORM_INT8);
72		case GL_LUMINANCE:			return TextureFormat(TextureFormat::L,		TextureFormat::UNORM_INT8);
73		case GL_LUMINANCE_ALPHA:	return TextureFormat(TextureFormat::LA,		TextureFormat::UNORM_INT8);
74		case GL_RGB:				return TextureFormat(TextureFormat::RGB,	TextureFormat::UNORM_INT8);
75		case GL_RGBA:				return TextureFormat(TextureFormat::RGBA,	TextureFormat::UNORM_INT8);
76		default:
77			throw tcu::InternalError(string("Can't map GL unsized internal format (") + tcu::toHex(internalFormat).toString() + ") to texture format");
78	}
79}
80
81enum
82{
83	VIEWPORT_WIDTH	= 256,
84	VIEWPORT_HEIGHT	= 256
85};
86
87static inline int maxLevelCount (int width, int height)
88{
89	return (int)deLog2Floor32(de::max(width, height))+1;
90}
91
92static inline int maxLevelCount (int width, int height, int depth)
93{
94	return (int)deLog2Floor32(de::max(width, de::max(height, depth)))+1;
95}
96
97template <int Size>
98static 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))
99{
100	tcu::Vector<float, Size> res;
101	for (int ndx = 0; ndx < Size; ndx++)
102		res[ndx] = rnd.getFloat(minVal[ndx], maxVal[ndx]);
103	return res;
104}
105
106static const deUint32 s_cubeMapFaces[] =
107{
108	GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
109	GL_TEXTURE_CUBE_MAP_POSITIVE_X,
110	GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
111	GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
112	GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
113	GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
114};
115
116static tcu::IVec4 getPixelFormatCompareDepth (const tcu::PixelFormat& pixelFormat, tcu::TextureFormat textureFormat)
117{
118	switch (textureFormat.order)
119	{
120		case tcu::TextureFormat::L:
121		case tcu::TextureFormat::LA:
122			return tcu::IVec4(pixelFormat.redBits, pixelFormat.redBits, pixelFormat.redBits, pixelFormat.alphaBits);
123		default:
124			return tcu::IVec4(pixelFormat.redBits, pixelFormat.greenBits, pixelFormat.blueBits, pixelFormat.alphaBits);
125	}
126}
127
128static IVec4 getEffectiveTextureFormatBitDepth (tcu::TextureFormat textureFormat)
129{
130	if (textureFormat.order == tcu::TextureFormat::DS)
131	{
132		// When sampling depth-stencil texture, we actually sample just
133		// the depth component.
134		return tcu::getTextureFormatBitDepth(tcu::getEffectiveDepthStencilTextureFormat(textureFormat, tcu::Sampler::MODE_DEPTH));
135	}
136	else
137		return tcu::getTextureFormatBitDepth(textureFormat);
138}
139
140static tcu::UVec4 computeCompareThreshold (const tcu::PixelFormat& pixelFormat, tcu::TextureFormat textureFormat)
141{
142	const IVec4		texFormatBits		= getEffectiveTextureFormatBitDepth(textureFormat);
143	const IVec4		pixelFormatBits		= getPixelFormatCompareDepth(pixelFormat, textureFormat);
144	const IVec4		accurateFmtBits		= min(pixelFormatBits, texFormatBits);
145	const IVec4		compareBits			= select(accurateFmtBits, IVec4(8), greaterThan(accurateFmtBits, IVec4(0))) - 1;
146
147	return (IVec4(1) << (8-compareBits)).asUint();
148}
149
150class TextureSpecCase : public TestCase, public sglr::ContextWrapper
151{
152public:
153							TextureSpecCase		(Context& context, const char* name, const char* desc);
154							~TextureSpecCase	(void);
155
156	IterateResult			iterate				(void);
157
158protected:
159	virtual void			createTexture		(void)																	= DE_NULL;
160	virtual void			verifyTexture		(sglr::GLContext& gles3Context, sglr::ReferenceContext& refContext)	= DE_NULL;
161
162	// Utilities.
163	void					renderTex			(tcu::Surface& dst, deUint32 program, int width, int height);
164	void					readPixels			(tcu::Surface& dst, int x, int y, int width, int height);
165
166private:
167							TextureSpecCase		(const TextureSpecCase& other);
168	TextureSpecCase&		operator=			(const TextureSpecCase& other);
169};
170
171TextureSpecCase::TextureSpecCase (Context& context, const char* name, const char* desc)
172	: TestCase(context, name, desc)
173{
174}
175
176TextureSpecCase::~TextureSpecCase (void)
177{
178}
179
180TextureSpecCase::IterateResult TextureSpecCase::iterate (void)
181{
182	glu::RenderContext&			renderCtx				= TestCase::m_context.getRenderContext();
183	const tcu::RenderTarget&	renderTarget			= renderCtx.getRenderTarget();
184	tcu::TestLog&				log						= m_testCtx.getLog();
185
186	if (renderTarget.getWidth() < VIEWPORT_WIDTH || renderTarget.getHeight() < VIEWPORT_HEIGHT)
187		throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
188
189	// Context size, and viewport for GLES3
190	de::Random		rnd			(deStringHash(getName()));
191	int				width		= deMin32(renderTarget.getWidth(),	VIEWPORT_WIDTH);
192	int				height		= deMin32(renderTarget.getHeight(),	VIEWPORT_HEIGHT);
193	int				x			= rnd.getInt(0, renderTarget.getWidth()		- width);
194	int				y			= rnd.getInt(0, renderTarget.getHeight()	- height);
195
196	// Contexts.
197	sglr::GLContext					gles3Context	(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height));
198	sglr::ReferenceContextBuffers	refBuffers		(tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), 0 /* depth */, 0 /* stencil */, width, height);
199	sglr::ReferenceContext			refContext		(sglr::ReferenceContextLimits(renderCtx), refBuffers.getColorbuffer(), refBuffers.getDepthbuffer(), refBuffers.getStencilbuffer());
200
201	// Clear color buffer.
202	for (int ndx = 0; ndx < 2; ndx++)
203	{
204		setContext(ndx ? (sglr::Context*)&refContext : (sglr::Context*)&gles3Context);
205		glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
206		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
207	}
208
209	// Construct texture using both GLES3 and reference contexts.
210	for (int ndx = 0; ndx < 2; ndx++)
211	{
212		setContext(ndx ? (sglr::Context*)&refContext : (sglr::Context*)&gles3Context);
213		createTexture();
214		TCU_CHECK(glGetError() == GL_NO_ERROR);
215	}
216
217	// Initialize case result to pass.
218	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
219
220	// Disable logging.
221	gles3Context.enableLogging(0);
222
223	// Verify results.
224	verifyTexture(gles3Context, refContext);
225
226	return STOP;
227}
228
229void TextureSpecCase::renderTex (tcu::Surface& dst, deUint32 program, int width, int height)
230{
231	int		targetW		= getWidth();
232	int		targetH		= getHeight();
233
234	float	w			= (float)width	/ (float)targetW;
235	float	h			= (float)height	/ (float)targetH;
236
237	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));
238
239	// Read pixels back.
240	readPixels(dst, 0, 0, width, height);
241}
242
243void TextureSpecCase::readPixels (tcu::Surface& dst, int x, int y, int width, int height)
244{
245	dst.setSize(width, height);
246	glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, dst.getAccess().getDataPtr());
247}
248
249class Texture2DSpecCase : public TextureSpecCase
250{
251public:
252							Texture2DSpecCase	(Context& context, const char* name, const char* desc, const tcu::TextureFormat& format, int width, int height, int numLevels);
253							~Texture2DSpecCase	(void);
254
255protected:
256	virtual void			verifyTexture		(sglr::GLContext& gles3Context, sglr::ReferenceContext& refContext);
257
258	tcu::TextureFormat		m_texFormat;
259	tcu::TextureFormatInfo	m_texFormatInfo;
260	int						m_width;
261	int						m_height;
262	int						m_numLevels;
263};
264
265Texture2DSpecCase::Texture2DSpecCase (Context& context, const char* name, const char* desc, const tcu::TextureFormat& format, int width, int height, int numLevels)
266	: TextureSpecCase		(context, name, desc)
267	, m_texFormat			(format)
268	, m_texFormatInfo		(tcu::getTextureFormatInfo(format))
269	, m_width				(width)
270	, m_height				(height)
271	, m_numLevels			(numLevels)
272{
273}
274
275Texture2DSpecCase::~Texture2DSpecCase (void)
276{
277}
278
279void Texture2DSpecCase::verifyTexture (sglr::GLContext& gles3Context, sglr::ReferenceContext& refContext)
280{
281	Texture2DShader shader			(DataTypes() << glu::getSampler2DType(m_texFormat), glu::TYPE_FLOAT_VEC4);
282	deUint32		shaderIDgles	= gles3Context.createProgram(&shader);
283	deUint32		shaderIDRef		= refContext.createProgram(&shader);
284
285	shader.setTexScaleBias(0, m_texFormatInfo.lookupScale, m_texFormatInfo.lookupBias);
286
287	// Set state.
288	for (int ndx = 0; ndx < 2; ndx++)
289	{
290		sglr::Context* ctx = ndx ? static_cast<sglr::Context*>(&refContext) : static_cast<sglr::Context*>(&gles3Context);
291
292		setContext(ctx);
293
294		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	GL_NEAREST_MIPMAP_NEAREST);
295		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
296		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
297		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
298		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL,	m_numLevels-1);
299	}
300
301	for (int levelNdx = 0; levelNdx < m_numLevels; levelNdx++)
302	{
303		int				levelW		= de::max(1, m_width >> levelNdx);
304		int				levelH		= de::max(1, m_height >> levelNdx);
305		tcu::Surface	reference;
306		tcu::Surface	result;
307
308		for (int ndx = 0; ndx < 2; ndx++)
309		{
310			tcu::Surface&	dst			= ndx ? reference									: result;
311			sglr::Context*	ctx			= ndx ? static_cast<sglr::Context*>(&refContext)	: static_cast<sglr::Context*>(&gles3Context);
312			deUint32		shaderID	= ndx ? shaderIDRef									: shaderIDgles;
313
314			setContext(ctx);
315			shader.setUniforms(*ctx, shaderID);
316			renderTex(dst, shaderID, levelW, levelH);
317		}
318
319		UVec4			threshold	= computeCompareThreshold(m_context.getRenderTarget().getPixelFormat(), m_texFormat);
320		string			levelStr	= de::toString(levelNdx);
321		string			name		= string("Level") + levelStr;
322		string			desc		= string("Level ") + levelStr;
323		bool			isOk		= tcu::intThresholdCompare(m_testCtx.getLog(), name.c_str(), desc.c_str(), reference.getAccess(), result.getAccess(), threshold,
324															   levelNdx == 0 ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
325
326		if (!isOk)
327		{
328			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
329			break;
330		}
331	}
332}
333
334class TextureCubeSpecCase : public TextureSpecCase
335{
336public:
337							TextureCubeSpecCase		(Context& context, const char* name, const char* desc, const tcu::TextureFormat& format, int size, int numLevels);
338							~TextureCubeSpecCase	(void);
339
340protected:
341	virtual void			verifyTexture			(sglr::GLContext& gles3Context, sglr::ReferenceContext& refContext);
342
343	tcu::TextureFormat		m_texFormat;
344	tcu::TextureFormatInfo	m_texFormatInfo;
345	int						m_size;
346	int						m_numLevels;
347};
348
349TextureCubeSpecCase::TextureCubeSpecCase (Context& context, const char* name, const char* desc, const tcu::TextureFormat& format, int size, int numLevels)
350	: TextureSpecCase		(context, name, desc)
351	, m_texFormat			(format)
352	, m_texFormatInfo		(tcu::getTextureFormatInfo(format))
353	, m_size				(size)
354	, m_numLevels			(numLevels)
355{
356}
357
358TextureCubeSpecCase::~TextureCubeSpecCase (void)
359{
360}
361
362void TextureCubeSpecCase::verifyTexture (sglr::GLContext& gles3Context, sglr::ReferenceContext& refContext)
363{
364	TextureCubeShader	shader			(glu::getSamplerCubeType(m_texFormat), glu::TYPE_FLOAT_VEC4);
365	deUint32			shaderIDgles	= gles3Context.createProgram(&shader);
366	deUint32			shaderIDRef		= refContext.createProgram(&shader);
367
368	shader.setTexScaleBias(m_texFormatInfo.lookupScale, m_texFormatInfo.lookupBias);
369
370	// Set state.
371	for (int ndx = 0; ndx < 2; ndx++)
372	{
373		sglr::Context* ctx = ndx ? static_cast<sglr::Context*>(&refContext) : static_cast<sglr::Context*>(&gles3Context);
374
375		setContext(ctx);
376
377		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,	GL_NEAREST_MIPMAP_NEAREST);
378		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
379		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
380		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
381		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL,	m_numLevels-1);
382	}
383
384	for (int levelNdx = 0; levelNdx < m_numLevels; levelNdx++)
385	{
386		int		levelSize	= de::max(1, m_size >> levelNdx);
387		bool	isOk		= true;
388
389		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
390		{
391			tcu::Surface	reference;
392			tcu::Surface	result;
393
394			if (levelSize <= 2)
395				continue; // Fuzzy compare doesn't work for images this small.
396
397			shader.setFace((tcu::CubeFace)face);
398
399			for (int ndx = 0; ndx < 2; ndx++)
400			{
401				tcu::Surface&	dst			= ndx ? reference									: result;
402				sglr::Context*	ctx			= ndx ? static_cast<sglr::Context*>(&refContext)	: static_cast<sglr::Context*>(&gles3Context);
403				deUint32		shaderID	= ndx ? shaderIDRef									: shaderIDgles;
404
405				setContext(ctx);
406				shader.setUniforms(*ctx, shaderID);
407				renderTex(dst, shaderID, levelSize, levelSize);
408			}
409
410			const float		threshold	= 0.02f;
411			string			faceStr		= de::toString((tcu::CubeFace)face);
412			string			levelStr	= de::toString(levelNdx);
413			string			name		= string("Level") + levelStr;
414			string			desc		= string("Level ") + levelStr + ", face " + faceStr;
415			bool			isFaceOk	= tcu::fuzzyCompare(m_testCtx.getLog(), name.c_str(), desc.c_str(), reference, result, threshold,
416															levelNdx == 0 ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
417
418			if (!isFaceOk)
419			{
420				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
421				isOk = false;
422				break;
423			}
424		}
425
426		if (!isOk)
427			break;
428	}
429}
430
431class Texture2DArraySpecCase : public TextureSpecCase
432{
433public:
434							Texture2DArraySpecCase	(Context& context, const char* name, const char* desc, const tcu::TextureFormat& format, int width, int height, int numLayers, int numLevels);
435							~Texture2DArraySpecCase	(void);
436
437protected:
438	virtual void			verifyTexture			(sglr::GLContext& gles3Context, sglr::ReferenceContext& refContext);
439
440	tcu::TextureFormat		m_texFormat;
441	tcu::TextureFormatInfo	m_texFormatInfo;
442	int						m_width;
443	int						m_height;
444	int						m_numLayers;
445	int						m_numLevels;
446};
447
448Texture2DArraySpecCase::Texture2DArraySpecCase (Context& context, const char* name, const char* desc, const tcu::TextureFormat& format, int width, int height, int numLayers, int numLevels)
449	: TextureSpecCase		(context, name, desc)
450	, m_texFormat			(format)
451	, m_texFormatInfo		(tcu::getTextureFormatInfo(format))
452	, m_width				(width)
453	, m_height				(height)
454	, m_numLayers			(numLayers)
455	, m_numLevels			(numLevels)
456{
457}
458
459Texture2DArraySpecCase::~Texture2DArraySpecCase (void)
460{
461}
462
463void Texture2DArraySpecCase::verifyTexture (sglr::GLContext& gles3Context, sglr::ReferenceContext& refContext)
464{
465	Texture2DArrayShader	shader			(glu::getSampler2DArrayType(m_texFormat), glu::TYPE_FLOAT_VEC4);
466	deUint32				shaderIDgles	= gles3Context.createProgram(&shader);
467	deUint32				shaderIDRef		= refContext.createProgram(&shader);
468
469	shader.setTexScaleBias(m_texFormatInfo.lookupScale, m_texFormatInfo.lookupBias);
470
471	// Set state.
472	for (int ndx = 0; ndx < 2; ndx++)
473	{
474		sglr::Context* ctx = ndx ? static_cast<sglr::Context*>(&refContext) : static_cast<sglr::Context*>(&gles3Context);
475
476		setContext(ctx);
477
478		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER,	GL_NEAREST_MIPMAP_NEAREST);
479		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
480		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
481		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
482		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_R,		GL_CLAMP_TO_EDGE);
483		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL,	m_numLevels-1);
484	}
485
486	for (int layerNdx = 0; layerNdx < m_numLayers; layerNdx++)
487	{
488		bool layerOk = true;
489
490		shader.setLayer(layerNdx);
491
492		for (int levelNdx = 0; levelNdx < m_numLevels; levelNdx++)
493		{
494			int				levelW		= de::max(1, m_width	>> levelNdx);
495			int				levelH		= de::max(1, m_height	>> levelNdx);
496			tcu::Surface	reference;
497			tcu::Surface	result;
498
499			for (int ndx = 0; ndx < 2; ndx++)
500			{
501				tcu::Surface&	dst			= ndx ? reference									: result;
502				sglr::Context*	ctx			= ndx ? static_cast<sglr::Context*>(&refContext)	: static_cast<sglr::Context*>(&gles3Context);
503				deUint32		shaderID	= ndx ? shaderIDRef									: shaderIDgles;
504
505				setContext(ctx);
506				shader.setUniforms(*ctx, shaderID);
507				renderTex(dst, shaderID, levelW, levelH);
508			}
509
510			UVec4			threshold	= computeCompareThreshold(m_context.getRenderTarget().getPixelFormat(), m_texFormat);
511			string			levelStr	= de::toString(levelNdx);
512			string			layerStr	= de::toString(layerNdx);
513			string			name		= string("Layer") + layerStr + "Level" + levelStr;
514			string			desc		= string("Layer ") + layerStr + ", Level " + levelStr;
515			bool			depthOk		= tcu::intThresholdCompare(m_testCtx.getLog(), name.c_str(), desc.c_str(), reference.getAccess(), result.getAccess(), threshold,
516																   (levelNdx == 0 && layerNdx == 0) ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
517
518			if (!depthOk)
519			{
520				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
521				layerOk = false;
522				break;
523			}
524		}
525
526		if (!layerOk)
527			break;
528	}
529}
530
531class Texture3DSpecCase : public TextureSpecCase
532{
533public:
534							Texture3DSpecCase	(Context& context, const char* name, const char* desc, const tcu::TextureFormat& format, int width, int height, int depth, int numLevels);
535							~Texture3DSpecCase	(void);
536
537protected:
538	virtual void			verifyTexture		(sglr::GLContext& gles3Context, sglr::ReferenceContext& refContext);
539
540	tcu::TextureFormat		m_texFormat;
541	tcu::TextureFormatInfo	m_texFormatInfo;
542	int						m_width;
543	int						m_height;
544	int						m_depth;
545	int						m_numLevels;
546};
547
548Texture3DSpecCase::Texture3DSpecCase (Context& context, const char* name, const char* desc, const tcu::TextureFormat& format, int width, int height, int depth, int numLevels)
549	: TextureSpecCase		(context, name, desc)
550	, m_texFormat			(format)
551	, m_texFormatInfo		(tcu::getTextureFormatInfo(format))
552	, m_width				(width)
553	, m_height				(height)
554	, m_depth				(depth)
555	, m_numLevels			(numLevels)
556{
557}
558
559Texture3DSpecCase::~Texture3DSpecCase (void)
560{
561}
562
563void Texture3DSpecCase::verifyTexture (sglr::GLContext& gles3Context, sglr::ReferenceContext& refContext)
564{
565	Texture3DShader shader			(glu::getSampler3DType(m_texFormat), glu::TYPE_FLOAT_VEC4);
566	deUint32		shaderIDgles	= gles3Context.createProgram(&shader);
567	deUint32		shaderIDRef		= refContext.createProgram(&shader);
568
569	shader.setTexScaleBias(m_texFormatInfo.lookupScale, m_texFormatInfo.lookupBias);
570
571	// Set state.
572	for (int ndx = 0; ndx < 2; ndx++)
573	{
574		sglr::Context* ctx = ndx ? static_cast<sglr::Context*>(&refContext) : static_cast<sglr::Context*>(&gles3Context);
575
576		setContext(ctx);
577
578		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER,	GL_NEAREST_MIPMAP_NEAREST);
579		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
580		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
581		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
582		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R,		GL_CLAMP_TO_EDGE);
583		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL,	m_numLevels-1);
584	}
585
586	for (int levelNdx = 0; levelNdx < m_numLevels; levelNdx++)
587	{
588		int		levelW		= de::max(1, m_width	>> levelNdx);
589		int		levelH		= de::max(1, m_height	>> levelNdx);
590		int		levelD		= de::max(1, m_depth	>> levelNdx);
591		bool	levelOk		= true;
592
593		for (int depth = 0; depth < levelD; depth++)
594		{
595			tcu::Surface	reference;
596			tcu::Surface	result;
597
598			shader.setDepth(((float)depth + 0.5f) / (float)levelD);
599
600			for (int ndx = 0; ndx < 2; ndx++)
601			{
602				tcu::Surface&	dst			= ndx ? reference									: result;
603				sglr::Context*	ctx			= ndx ? static_cast<sglr::Context*>(&refContext)	: static_cast<sglr::Context*>(&gles3Context);
604				deUint32		shaderID	= ndx ? shaderIDRef									: shaderIDgles;
605
606				setContext(ctx);
607				shader.setUniforms(*ctx, shaderID);
608				renderTex(dst, shaderID, levelW, levelH);
609			}
610
611			UVec4			threshold	= computeCompareThreshold(m_context.getRenderTarget().getPixelFormat(), m_texFormat);
612			string			levelStr	= de::toString(levelNdx);
613			string			sliceStr	= de::toString(depth);
614			string			name		= string("Level") + levelStr + "Slice" + sliceStr;
615			string			desc		= string("Level ") + levelStr + ", Slice " + sliceStr;
616			bool			depthOk		= tcu::intThresholdCompare(m_testCtx.getLog(), name.c_str(), desc.c_str(), reference.getAccess(), result.getAccess(), threshold,
617																   (levelNdx == 0 && depth == 0) ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
618
619			if (!depthOk)
620			{
621				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
622				levelOk = false;
623				break;
624			}
625		}
626
627		if (!levelOk)
628			break;
629	}
630}
631
632// Basic TexImage2D() with 2D texture usage
633class BasicTexImage2DCase : public Texture2DSpecCase
634{
635public:
636	// Unsized internal format.
637	BasicTexImage2DCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, int width, int height)
638		: Texture2DSpecCase	(context, name, desc, glu::mapGLTransferFormat(format, dataType), width, height, maxLevelCount(width, height))
639		, m_internalFormat	(format)
640		, m_format			(format)
641		, m_dataType		(dataType)
642	{
643	}
644
645	// Sized internal format.
646	BasicTexImage2DCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int width, int height)
647		: Texture2DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, maxLevelCount(width, height))
648		, m_internalFormat	(internalFormat)
649		, m_format			(GL_NONE)
650		, m_dataType		(GL_NONE)
651	{
652		glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
653		m_format	= fmt.format;
654		m_dataType	= fmt.dataType;
655	}
656
657protected:
658	void createTexture (void)
659	{
660		deUint32			tex			= 0;
661		tcu::TextureLevel	levelData	(m_texFormat);
662		de::Random			rnd			(deStringHash(getName()));
663
664		glGenTextures(1, &tex);
665		glBindTexture(GL_TEXTURE_2D, tex);
666		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
667
668		for (int ndx = 0; ndx < m_numLevels; ndx++)
669		{
670			int		levelW		= de::max(1, m_width >> ndx);
671			int		levelH		= de::max(1, m_height >> ndx);
672			Vec4	gMin		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
673			Vec4	gMax		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
674
675			levelData.setSize(levelW, levelH);
676			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
677
678			glTexImage2D(GL_TEXTURE_2D, ndx, m_internalFormat, levelW, levelH, 0, m_format, m_dataType, levelData.getAccess().getDataPtr());
679		}
680	}
681
682	deUint32	m_internalFormat;
683	deUint32	m_format;
684	deUint32	m_dataType;
685};
686
687// Basic TexImage2D() with cubemap usage
688class BasicTexImageCubeCase : public TextureCubeSpecCase
689{
690public:
691	// Unsized formats.
692	BasicTexImageCubeCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, int size)
693		: TextureCubeSpecCase	(context, name, desc, glu::mapGLTransferFormat(format, dataType), size, deLog2Floor32(size)+1)
694		, m_internalFormat		(format)
695		, m_format				(format)
696		, m_dataType			(dataType)
697	{
698	}
699
700	// Sized internal formats.
701	BasicTexImageCubeCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int size)
702		: TextureCubeSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, deLog2Floor32(size)+1)
703		, m_internalFormat		(internalFormat)
704		, m_format				(GL_NONE)
705		, m_dataType			(GL_NONE)
706	{
707		glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
708		m_format	= fmt.format;
709		m_dataType	= fmt.dataType;
710	}
711
712protected:
713	void createTexture (void)
714	{
715		deUint32			tex			= 0;
716		tcu::TextureLevel	levelData	(m_texFormat);
717		de::Random			rnd			(deStringHash(getName()));
718
719		glGenTextures(1, &tex);
720		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
721		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
722
723		for (int ndx = 0; ndx < m_numLevels; ndx++)
724		{
725			int levelSize = de::max(1, m_size >> ndx);
726
727			levelData.setSize(levelSize, levelSize);
728
729			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
730			{
731				Vec4 gMin = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
732				Vec4 gMax = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
733
734				tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
735
736				glTexImage2D(s_cubeMapFaces[face], ndx, m_internalFormat, levelSize, levelSize, 0, m_format, m_dataType, levelData.getAccess().getDataPtr());
737			}
738		}
739	}
740
741	deUint32	m_internalFormat;
742	deUint32	m_format;
743	deUint32	m_dataType;
744};
745
746// Basic TexImage3D() with 2D array texture usage
747class BasicTexImage2DArrayCase : public Texture2DArraySpecCase
748{
749public:
750	BasicTexImage2DArrayCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int width, int height, int numLayers)
751		: Texture2DArraySpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, numLayers, maxLevelCount(width, height))
752		, m_internalFormat			(internalFormat)
753	{
754	}
755
756protected:
757	void createTexture (void)
758	{
759		deUint32				tex			= 0;
760		tcu::TextureLevel		levelData	(m_texFormat);
761		de::Random				rnd			(deStringHash(getName()));
762		glu::TransferFormat		transferFmt	= glu::getTransferFormat(m_texFormat);
763
764		glGenTextures(1, &tex);
765		glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
766		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
767
768		for (int ndx = 0; ndx < m_numLevels; ndx++)
769		{
770			int		levelW		= de::max(1, m_width	>> ndx);
771			int		levelH		= de::max(1, m_height	>> ndx);
772			Vec4	gMin		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
773			Vec4	gMax		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
774
775			levelData.setSize(levelW, levelH, m_numLayers);
776			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
777
778			glTexImage3D(GL_TEXTURE_2D_ARRAY, ndx, m_internalFormat, levelW, levelH, m_numLayers, 0, transferFmt.format, transferFmt.dataType, levelData.getAccess().getDataPtr());
779		}
780	}
781
782	deUint32 m_internalFormat;
783};
784
785// Basic TexImage3D() with 3D texture usage
786class BasicTexImage3DCase : public Texture3DSpecCase
787{
788public:
789	BasicTexImage3DCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int width, int height, int depth)
790		: Texture3DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth, maxLevelCount(width, height, depth))
791		, m_internalFormat	(internalFormat)
792	{
793	}
794
795protected:
796	void createTexture (void)
797	{
798		deUint32				tex			= 0;
799		tcu::TextureLevel		levelData	(m_texFormat);
800		de::Random				rnd			(deStringHash(getName()));
801		glu::TransferFormat		transferFmt	= glu::getTransferFormat(m_texFormat);
802
803		glGenTextures(1, &tex);
804		glBindTexture(GL_TEXTURE_3D, tex);
805		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
806
807		for (int ndx = 0; ndx < m_numLevels; ndx++)
808		{
809			int		levelW		= de::max(1, m_width	>> ndx);
810			int		levelH		= de::max(1, m_height	>> ndx);
811			int		levelD		= de::max(1, m_depth	>> ndx);
812			Vec4	gMin		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
813			Vec4	gMax		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
814
815			levelData.setSize(levelW, levelH, levelD);
816			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
817
818			glTexImage3D(GL_TEXTURE_3D, ndx, m_internalFormat, levelW, levelH, levelD, 0, transferFmt.format, transferFmt.dataType, levelData.getAccess().getDataPtr());
819		}
820	}
821
822	deUint32 m_internalFormat;
823};
824
825// Randomized 2D texture specification using TexImage2D
826class RandomOrderTexImage2DCase : public Texture2DSpecCase
827{
828public:
829	RandomOrderTexImage2DCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, int width, int height)
830		: Texture2DSpecCase	(context, name, desc, glu::mapGLTransferFormat(format, dataType), width, height, maxLevelCount(width, height))
831		, m_internalFormat	(format)
832		, m_format			(format)
833		, m_dataType		(dataType)
834	{
835	}
836
837	RandomOrderTexImage2DCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int width, int height)
838		: Texture2DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, maxLevelCount(width, height))
839		, m_internalFormat	(internalFormat)
840		, m_format			(GL_NONE)
841		, m_dataType		(GL_NONE)
842	{
843		glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
844		m_format	= fmt.format;
845		m_dataType	= fmt.dataType;
846	}
847
848protected:
849	void createTexture (void)
850	{
851		deUint32			tex			= 0;
852		tcu::TextureLevel	levelData	(m_texFormat);
853		de::Random			rnd			(deStringHash(getName()));
854
855		glGenTextures(1, &tex);
856		glBindTexture(GL_TEXTURE_2D, tex);
857		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
858
859		vector<int>			levels		(m_numLevels);
860
861		for (int i = 0; i < m_numLevels; i++)
862			levels[i] = i;
863		rnd.shuffle(levels.begin(), levels.end());
864
865		for (int ndx = 0; ndx < m_numLevels; ndx++)
866		{
867			int		levelNdx	= levels[ndx];
868			int		levelW		= de::max(1, m_width	>> levelNdx);
869			int		levelH		= de::max(1, m_height	>> levelNdx);
870			Vec4	gMin		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
871			Vec4	gMax		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
872
873			levelData.setSize(levelW, levelH);
874			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
875
876			glTexImage2D(GL_TEXTURE_2D, levelNdx, m_internalFormat, levelW, levelH, 0, m_format, m_dataType, levelData.getAccess().getDataPtr());
877		}
878	}
879
880	deUint32	m_internalFormat;
881	deUint32	m_format;
882	deUint32	m_dataType;
883};
884
885// Randomized cubemap texture specification using TexImage2D
886class RandomOrderTexImageCubeCase : public TextureCubeSpecCase
887{
888public:
889	RandomOrderTexImageCubeCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, int size)
890		: TextureCubeSpecCase	(context, name, desc, glu::mapGLTransferFormat(format, dataType), size, deLog2Floor32(size)+1)
891		, m_internalFormat		(GL_NONE)
892		, m_format				(format)
893		, m_dataType			(dataType)
894	{
895	}
896
897	RandomOrderTexImageCubeCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int size)
898		: TextureCubeSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, deLog2Floor32(size)+1)
899		, m_internalFormat		(internalFormat)
900		, m_format				(GL_NONE)
901		, m_dataType			(GL_NONE)
902	{
903		glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
904		m_format	= fmt.format;
905		m_dataType	= fmt.dataType;
906	}
907
908protected:
909	void createTexture (void)
910	{
911		deUint32			tex			= 0;
912		tcu::TextureLevel	levelData	(m_texFormat);
913		de::Random			rnd			(deStringHash(getName()));
914
915		glGenTextures(1, &tex);
916		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
917		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
918
919		// Level-face pairs.
920		vector<pair<int, tcu::CubeFace> >	images	(m_numLevels*6);
921
922		for (int ndx = 0; ndx < m_numLevels; ndx++)
923			for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
924				images[ndx*6 + face] = std::make_pair(ndx, (tcu::CubeFace)face);
925
926		rnd.shuffle(images.begin(), images.end());
927
928		for (int ndx = 0; ndx < (int)images.size(); ndx++)
929		{
930			int				levelNdx	= images[ndx].first;
931			tcu::CubeFace	face		= images[ndx].second;
932			int				levelSize	= de::max(1, m_size >> levelNdx);
933			Vec4			gMin		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
934			Vec4			gMax		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
935
936			levelData.setSize(levelSize, levelSize);
937			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
938
939			glTexImage2D(s_cubeMapFaces[face], levelNdx, m_internalFormat, levelSize, levelSize, 0, m_format, m_dataType, levelData.getAccess().getDataPtr());
940		}
941	}
942
943	deUint32	m_internalFormat;
944	deUint32	m_format;
945	deUint32	m_dataType;
946};
947
948// TexImage2D() unpack alignment case.
949class TexImage2DAlignCase : public Texture2DSpecCase
950{
951public:
952	TexImage2DAlignCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, int width, int height, int numLevels, int alignment)
953		: Texture2DSpecCase	(context, name, desc, glu::mapGLTransferFormat(format, dataType), width, height, numLevels)
954		, m_internalFormat	(format)
955		, m_format			(format)
956		, m_dataType		(dataType)
957		, m_alignment		(alignment)
958	{
959	}
960
961	TexImage2DAlignCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int width, int height, int numLevels, int alignment)
962		: Texture2DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, numLevels)
963		, m_internalFormat	(internalFormat)
964		, m_format			(GL_NONE)
965		, m_dataType		(GL_NONE)
966		, m_alignment		(alignment)
967	{
968		glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
969		m_format	= fmt.format;
970		m_dataType	= fmt.dataType;
971	}
972
973protected:
974	void createTexture (void)
975	{
976		deUint32			tex			= 0;
977		vector<deUint8>		data;
978
979		glGenTextures(1, &tex);
980		glBindTexture(GL_TEXTURE_2D, tex);
981		glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
982
983		for (int ndx = 0; ndx < m_numLevels; ndx++)
984		{
985			int		levelW		= de::max(1, m_width >> ndx);
986			int		levelH		= de::max(1, m_height >> ndx);
987			Vec4	colorA		= Vec4(1.0f, 0.0f, 0.0f, 1.0f)*(m_texFormatInfo.valueMax-m_texFormatInfo.valueMin) + m_texFormatInfo.valueMin;
988			Vec4	colorB		= Vec4(0.0f, 1.0f, 0.0f, 1.0f)*(m_texFormatInfo.valueMax-m_texFormatInfo.valueMin) + m_texFormatInfo.valueMin;
989			int		rowPitch	= deAlign32(levelW*m_texFormat.getPixelSize(), m_alignment);
990			int		cellSize	= de::max(1, de::min(levelW >> 2, levelH >> 2));
991
992			data.resize(rowPitch*levelH);
993			tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, levelW, levelH, 1, rowPitch, 0, &data[0]), cellSize, colorA, colorB);
994
995			glTexImage2D(GL_TEXTURE_2D, ndx, m_internalFormat, levelW, levelH, 0, m_format, m_dataType, &data[0]);
996		}
997	}
998
999	deUint32	m_internalFormat;
1000	deUint32	m_format;
1001	deUint32	m_dataType;
1002	int			m_alignment;
1003};
1004
1005// TexImage2D() unpack alignment case.
1006class TexImageCubeAlignCase : public TextureCubeSpecCase
1007{
1008public:
1009	TexImageCubeAlignCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, int size, int numLevels, int alignment)
1010		: TextureCubeSpecCase	(context, name, desc, glu::mapGLTransferFormat(format, dataType), size, numLevels)
1011		, m_internalFormat		(format)
1012		, m_format				(format)
1013		, m_dataType			(dataType)
1014		, m_alignment			(alignment)
1015	{
1016	}
1017
1018	TexImageCubeAlignCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int size, int numLevels, int alignment)
1019		: TextureCubeSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, numLevels)
1020		, m_internalFormat		(internalFormat)
1021		, m_format				(GL_NONE)
1022		, m_dataType			(GL_NONE)
1023		, m_alignment			(alignment)
1024	{
1025		glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
1026		m_format	= fmt.format;
1027		m_dataType	= fmt.dataType;
1028	}
1029
1030protected:
1031	void createTexture (void)
1032	{
1033		deUint32			tex			= 0;
1034		vector<deUint8>		data;
1035
1036		glGenTextures(1, &tex);
1037		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1038		glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
1039
1040		for (int ndx = 0; ndx < m_numLevels; ndx++)
1041		{
1042			int		levelSize	= de::max(1, m_size >> ndx);
1043			int		rowPitch	= deAlign32(m_texFormat.getPixelSize()*levelSize, m_alignment);
1044			Vec4	colorA		= Vec4(1.0f, 0.0f, 0.0f, 1.0f)*(m_texFormatInfo.valueMax-m_texFormatInfo.valueMin) + m_texFormatInfo.valueMin;
1045			Vec4	colorB		= Vec4(0.0f, 1.0f, 0.0f, 1.0f)*(m_texFormatInfo.valueMax-m_texFormatInfo.valueMin) + m_texFormatInfo.valueMin;
1046			int		cellSize	= de::max(1, levelSize >> 2);
1047
1048			data.resize(rowPitch*levelSize);
1049			tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, levelSize, levelSize, 1, rowPitch, 0, &data[0]), cellSize, colorA, colorB);
1050
1051			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1052				glTexImage2D(s_cubeMapFaces[face], ndx, m_internalFormat, levelSize, levelSize, 0, m_format, m_dataType, &data[0]);
1053		}
1054	}
1055
1056	deUint32	m_internalFormat;
1057	deUint32	m_format;
1058	deUint32	m_dataType;
1059	int			m_alignment;
1060};
1061
1062// TexImage2D() unpack parameters case.
1063class TexImage2DParamsCase : public Texture2DSpecCase
1064{
1065public:
1066	TexImage2DParamsCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int width, int height, int rowLength, int skipRows, int skipPixels, int alignment)
1067		: Texture2DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, 1)
1068		, m_internalFormat	(internalFormat)
1069		, m_rowLength		(rowLength)
1070		, m_skipRows		(skipRows)
1071		, m_skipPixels		(skipPixels)
1072		, m_alignment		(alignment)
1073	{
1074	}
1075
1076protected:
1077	void createTexture (void)
1078	{
1079		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
1080		int						pixelSize		= m_texFormat.getPixelSize();
1081		int						rowLength		= m_rowLength > 0 ? m_rowLength : m_width;
1082		int						rowPitch		= deAlign32(rowLength*pixelSize, m_alignment);
1083		int						height			= m_height + m_skipRows;
1084		deUint32				tex				= 0;
1085		vector<deUint8>			data;
1086
1087		DE_ASSERT(m_numLevels == 1);
1088
1089		// Fill data with grid.
1090		data.resize(rowPitch*height);
1091		{
1092			Vec4	cScale		= m_texFormatInfo.valueMax-m_texFormatInfo.valueMin;
1093			Vec4	cBias		= m_texFormatInfo.valueMin;
1094			Vec4	colorA		= Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
1095			Vec4	colorB		= Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias;
1096
1097			tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, 1, rowPitch, 0, &data[0] + m_skipRows*rowPitch + m_skipPixels*pixelSize), 4, colorA, colorB);
1098		}
1099
1100		glPixelStorei(GL_UNPACK_ROW_LENGTH,		m_rowLength);
1101		glPixelStorei(GL_UNPACK_SKIP_ROWS,		m_skipRows);
1102		glPixelStorei(GL_UNPACK_SKIP_PIXELS,	m_skipPixels);
1103		glPixelStorei(GL_UNPACK_ALIGNMENT,		m_alignment);
1104
1105		glGenTextures(1, &tex);
1106		glBindTexture(GL_TEXTURE_2D, tex);
1107		glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, transferFmt.format, transferFmt.dataType, &data[0]);
1108	}
1109
1110	deUint32	m_internalFormat;
1111	int			m_rowLength;
1112	int			m_skipRows;
1113	int			m_skipPixels;
1114	int			m_alignment;
1115};
1116
1117// TexImage3D() unpack parameters case.
1118class TexImage3DParamsCase : public Texture3DSpecCase
1119{
1120public:
1121	TexImage3DParamsCase (Context&		context,
1122						   const char*	name,
1123						   const char*	desc,
1124						   deUint32		internalFormat,
1125						   int			width,
1126						   int			height,
1127						   int			depth,
1128						   int			imageHeight,
1129						   int			rowLength,
1130						   int			skipImages,
1131						   int			skipRows,
1132						   int			skipPixels,
1133						   int			alignment)
1134		: Texture3DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth, 1)
1135		, m_internalFormat	(internalFormat)
1136		, m_imageHeight		(imageHeight)
1137		, m_rowLength		(rowLength)
1138		, m_skipImages		(skipImages)
1139		, m_skipRows		(skipRows)
1140		, m_skipPixels		(skipPixels)
1141		, m_alignment		(alignment)
1142	{
1143	}
1144
1145protected:
1146	void createTexture (void)
1147	{
1148		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
1149		int						pixelSize		= m_texFormat.getPixelSize();
1150		int						rowLength		= m_rowLength > 0 ? m_rowLength : m_width;
1151		int						rowPitch		= deAlign32(rowLength*pixelSize, m_alignment);
1152		int						imageHeight		= m_imageHeight > 0 ? m_imageHeight : m_height;
1153		int						slicePitch		= imageHeight*rowPitch;
1154		deUint32				tex				= 0;
1155		vector<deUint8>			data;
1156
1157		DE_ASSERT(m_numLevels == 1);
1158
1159		// Fill data with grid.
1160		data.resize(slicePitch*(m_depth+m_skipImages));
1161		{
1162			Vec4	cScale		= m_texFormatInfo.valueMax-m_texFormatInfo.valueMin;
1163			Vec4	cBias		= m_texFormatInfo.valueMin;
1164			Vec4	colorA		= Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
1165			Vec4	colorB		= Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias;
1166
1167			tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, m_depth, rowPitch, slicePitch, &data[0] + m_skipImages*slicePitch + m_skipRows*rowPitch + m_skipPixels*pixelSize), 4, colorA, colorB);
1168		}
1169
1170		glPixelStorei(GL_UNPACK_IMAGE_HEIGHT,	m_imageHeight);
1171		glPixelStorei(GL_UNPACK_ROW_LENGTH,		m_rowLength);
1172		glPixelStorei(GL_UNPACK_SKIP_IMAGES,	m_skipImages);
1173		glPixelStorei(GL_UNPACK_SKIP_ROWS,		m_skipRows);
1174		glPixelStorei(GL_UNPACK_SKIP_PIXELS,	m_skipPixels);
1175		glPixelStorei(GL_UNPACK_ALIGNMENT,		m_alignment);
1176
1177		glGenTextures(1, &tex);
1178		glBindTexture(GL_TEXTURE_3D, tex);
1179		glTexImage3D(GL_TEXTURE_3D, 0, m_internalFormat, m_width, m_height, m_depth, 0, transferFmt.format, transferFmt.dataType, &data[0]);
1180	}
1181
1182	deUint32	m_internalFormat;
1183	int			m_imageHeight;
1184	int			m_rowLength;
1185	int			m_skipImages;
1186	int			m_skipRows;
1187	int			m_skipPixels;
1188	int			m_alignment;
1189};
1190
1191// Basic TexSubImage2D() with 2D texture usage
1192class BasicTexSubImage2DCase : public Texture2DSpecCase
1193{
1194public:
1195	BasicTexSubImage2DCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, int width, int height)
1196		: Texture2DSpecCase	(context, name, desc, glu::mapGLTransferFormat(format, dataType), width, height, maxLevelCount(width, height))
1197		, m_internalFormat	(format)
1198		, m_format			(format)
1199		, m_dataType		(dataType)
1200	{
1201	}
1202
1203	BasicTexSubImage2DCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int width, int height)
1204		: Texture2DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, maxLevelCount(width, height))
1205		, m_internalFormat	(internalFormat)
1206		, m_format			(GL_NONE)
1207		, m_dataType		(GL_NONE)
1208	{
1209		glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
1210		m_format	= fmt.format;
1211		m_dataType	= fmt.dataType;
1212	}
1213
1214protected:
1215	void createTexture (void)
1216	{
1217		deUint32			tex			= 0;
1218		tcu::TextureLevel	data		(m_texFormat);
1219		de::Random			rnd			(deStringHash(getName()));
1220
1221		glGenTextures(1, &tex);
1222		glBindTexture(GL_TEXTURE_2D, tex);
1223		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1224
1225		// First specify full texture.
1226		for (int ndx = 0; ndx < m_numLevels; ndx++)
1227		{
1228			int		levelW		= de::max(1, m_width >> ndx);
1229			int		levelH		= de::max(1, m_height >> ndx);
1230			Vec4	gMin		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1231			Vec4	gMax		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1232
1233			data.setSize(levelW, levelH);
1234			tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
1235
1236			glTexImage2D(GL_TEXTURE_2D, ndx, m_internalFormat, levelW, levelH, 0, m_format, m_dataType, data.getAccess().getDataPtr());
1237		}
1238
1239		// Re-specify parts of each level.
1240		for (int ndx = 0; ndx < m_numLevels; ndx++)
1241		{
1242			int		levelW		= de::max(1, m_width >> ndx);
1243			int		levelH		= de::max(1, m_height >> ndx);
1244
1245			int		w			= rnd.getInt(1, levelW);
1246			int		h			= rnd.getInt(1, levelH);
1247			int		x			= rnd.getInt(0, levelW-w);
1248			int		y			= rnd.getInt(0, levelH-h);
1249
1250			Vec4	colorA		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1251			Vec4	colorB		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1252			int		cellSize	= rnd.getInt(2, 16);
1253
1254			data.setSize(w, h);
1255			tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
1256
1257			glTexSubImage2D(GL_TEXTURE_2D, ndx, x, y, w, h, m_format, m_dataType, data.getAccess().getDataPtr());
1258		}
1259	}
1260
1261	deUint32	m_internalFormat;
1262	deUint32	m_format;
1263	deUint32	m_dataType;
1264};
1265
1266// Basic TexSubImage2D() with cubemap usage
1267class BasicTexSubImageCubeCase : public TextureCubeSpecCase
1268{
1269public:
1270	BasicTexSubImageCubeCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, int size)
1271		: TextureCubeSpecCase	(context, name, desc, glu::mapGLTransferFormat(format, dataType), size, deLog2Floor32(size)+1)
1272		, m_internalFormat		(format)
1273		, m_format				(format)
1274		, m_dataType			(dataType)
1275	{
1276	}
1277
1278	BasicTexSubImageCubeCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int size)
1279		: TextureCubeSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, deLog2Floor32(size)+1)
1280		, m_internalFormat		(internalFormat)
1281		, m_format				(GL_NONE)
1282		, m_dataType			(GL_NONE)
1283	{
1284		glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
1285		m_format	= fmt.format;
1286		m_dataType	= fmt.dataType;
1287	}
1288
1289protected:
1290	void createTexture (void)
1291	{
1292		deUint32			tex			= 0;
1293		tcu::TextureLevel	data		(m_texFormat);
1294		de::Random			rnd			(deStringHash(getName()));
1295
1296		glGenTextures(1, &tex);
1297		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1298		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1299
1300		for (int ndx = 0; ndx < m_numLevels; ndx++)
1301		{
1302			int levelSize = de::max(1, m_size >> ndx);
1303
1304			data.setSize(levelSize, levelSize);
1305
1306			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1307			{
1308				Vec4 gMin = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1309				Vec4 gMax = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1310
1311				tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
1312
1313				glTexImage2D(s_cubeMapFaces[face], ndx, m_internalFormat, levelSize, levelSize, 0, m_format, m_dataType, data.getAccess().getDataPtr());
1314			}
1315		}
1316
1317		// Re-specify parts of each face and level.
1318		for (int ndx = 0; ndx < m_numLevels; ndx++)
1319		{
1320			int levelSize = de::max(1, m_size >> ndx);
1321
1322			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1323			{
1324				int		w			= rnd.getInt(1, levelSize);
1325				int		h			= rnd.getInt(1, levelSize);
1326				int		x			= rnd.getInt(0, levelSize-w);
1327				int		y			= rnd.getInt(0, levelSize-h);
1328
1329				Vec4	colorA		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1330				Vec4	colorB		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1331				int		cellSize	= rnd.getInt(2, 16);
1332
1333				data.setSize(w, h);
1334				tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
1335
1336				glTexSubImage2D(s_cubeMapFaces[face], ndx, x, y, w, h, m_format, m_dataType, data.getAccess().getDataPtr());
1337			}
1338		}
1339	}
1340
1341	deUint32	m_internalFormat;
1342	deUint32	m_format;
1343	deUint32	m_dataType;
1344};
1345
1346// TexSubImage2D() unpack parameters case.
1347class TexSubImage2DParamsCase : public Texture2DSpecCase
1348{
1349public:
1350	TexSubImage2DParamsCase (Context&		context,
1351							 const char*	name,
1352							 const char*	desc,
1353							 deUint32		internalFormat,
1354							 int			width,
1355							 int			height,
1356							 int			subX,
1357							 int			subY,
1358							 int			subW,
1359							 int			subH,
1360							 int			rowLength,
1361							 int			skipRows,
1362							 int			skipPixels,
1363							 int			alignment)
1364		: Texture2DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, 1)
1365		, m_internalFormat	(internalFormat)
1366		, m_subX			(subX)
1367		, m_subY			(subY)
1368		, m_subW			(subW)
1369		, m_subH			(subH)
1370		, m_rowLength		(rowLength)
1371		, m_skipRows		(skipRows)
1372		, m_skipPixels		(skipPixels)
1373		, m_alignment		(alignment)
1374	{
1375	}
1376
1377protected:
1378	void createTexture (void)
1379	{
1380		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
1381		int						pixelSize		= m_texFormat.getPixelSize();
1382		deUint32				tex				= 0;
1383		vector<deUint8>			data;
1384
1385		DE_ASSERT(m_numLevels == 1);
1386
1387		glGenTextures(1, &tex);
1388		glBindTexture(GL_TEXTURE_2D, tex);
1389
1390		// First fill texture with gradient.
1391		data.resize(deAlign32(m_width*pixelSize, 4)*m_height);
1392		tcu::fillWithComponentGradients(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, 1, deAlign32(m_width*pixelSize, 4), 0, &data[0]), m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1393		glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, transferFmt.format, transferFmt.dataType, &data[0]);
1394
1395		// Fill data with grid.
1396		{
1397			int		rowLength	= m_rowLength > 0 ? m_rowLength : m_subW;
1398			int		rowPitch	= deAlign32(rowLength*pixelSize, m_alignment);
1399			int		height		= m_subH + m_skipRows;
1400			Vec4	cScale		= m_texFormatInfo.valueMax-m_texFormatInfo.valueMin;
1401			Vec4	cBias		= m_texFormatInfo.valueMin;
1402			Vec4	colorA		= Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
1403			Vec4	colorB		= Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias;
1404
1405			data.resize(rowPitch*height);
1406			tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_subW, m_subH, 1, rowPitch, 0, &data[0] + m_skipRows*rowPitch + m_skipPixels*pixelSize), 4, colorA, colorB);
1407		}
1408
1409		glPixelStorei(GL_UNPACK_ROW_LENGTH,		m_rowLength);
1410		glPixelStorei(GL_UNPACK_SKIP_ROWS,		m_skipRows);
1411		glPixelStorei(GL_UNPACK_SKIP_PIXELS,	m_skipPixels);
1412		glPixelStorei(GL_UNPACK_ALIGNMENT,		m_alignment);
1413		glTexSubImage2D(GL_TEXTURE_2D, 0, m_subX, m_subY, m_subW, m_subH, transferFmt.format, transferFmt.dataType, &data[0]);
1414	}
1415
1416	deUint32	m_internalFormat;
1417	int			m_subX;
1418	int			m_subY;
1419	int			m_subW;
1420	int			m_subH;
1421	int			m_rowLength;
1422	int			m_skipRows;
1423	int			m_skipPixels;
1424	int			m_alignment;
1425};
1426
1427// Basic TexSubImage3D() with 3D texture usage
1428class BasicTexSubImage3DCase : public Texture3DSpecCase
1429{
1430public:
1431	BasicTexSubImage3DCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int width, int height, int depth)
1432		: Texture3DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth, maxLevelCount(width, height, depth))
1433		, m_internalFormat	(internalFormat)
1434	{
1435	}
1436
1437protected:
1438	void createTexture (void)
1439	{
1440		deUint32				tex				= 0;
1441		tcu::TextureLevel		data			(m_texFormat);
1442		de::Random				rnd				(deStringHash(getName()));
1443		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
1444
1445		glGenTextures(1, &tex);
1446		glBindTexture(GL_TEXTURE_3D, tex);
1447		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1448
1449		// First specify full texture.
1450		for (int ndx = 0; ndx < m_numLevels; ndx++)
1451		{
1452			int		levelW		= de::max(1, m_width >> ndx);
1453			int		levelH		= de::max(1, m_height >> ndx);
1454			int		levelD		= de::max(1, m_depth >> ndx);
1455			Vec4	gMin		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1456			Vec4	gMax		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1457
1458			data.setSize(levelW, levelH, levelD);
1459			tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
1460
1461			glTexImage3D(GL_TEXTURE_3D, ndx, m_internalFormat, levelW, levelH, levelD, 0, transferFmt.format, transferFmt.dataType, data.getAccess().getDataPtr());
1462		}
1463
1464		// Re-specify parts of each level.
1465		for (int ndx = 0; ndx < m_numLevels; ndx++)
1466		{
1467			int		levelW		= de::max(1, m_width >> ndx);
1468			int		levelH		= de::max(1, m_height >> ndx);
1469			int		levelD		= de::max(1, m_depth >> ndx);
1470
1471			int		w			= rnd.getInt(1, levelW);
1472			int		h			= rnd.getInt(1, levelH);
1473			int		d			= rnd.getInt(1, levelD);
1474			int		x			= rnd.getInt(0, levelW-w);
1475			int		y			= rnd.getInt(0, levelH-h);
1476			int		z			= rnd.getInt(0, levelD-d);
1477
1478			Vec4	colorA		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1479			Vec4	colorB		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1480			int		cellSize	= rnd.getInt(2, 16);
1481
1482			data.setSize(w, h, d);
1483			tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
1484
1485			glTexSubImage3D(GL_TEXTURE_3D, ndx, x, y, z, w, h, d, transferFmt.format, transferFmt.dataType, data.getAccess().getDataPtr());
1486		}
1487	}
1488
1489	deUint32 m_internalFormat;
1490};
1491
1492// TexSubImage2D() to texture initialized with empty data
1493class TexSubImage2DEmptyTexCase : public Texture2DSpecCase
1494{
1495public:
1496	TexSubImage2DEmptyTexCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, int width, int height)
1497		: Texture2DSpecCase	(context, name, desc, glu::mapGLTransferFormat(format, dataType), width, height, maxLevelCount(width, height))
1498		, m_internalFormat	(format)
1499		, m_format			(format)
1500		, m_dataType		(dataType)
1501	{
1502	}
1503
1504	TexSubImage2DEmptyTexCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int width, int height)
1505		: Texture2DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, maxLevelCount(width, height))
1506		, m_internalFormat	(internalFormat)
1507		, m_format			(GL_NONE)
1508		, m_dataType		(GL_NONE)
1509	{
1510		glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
1511		m_format	= fmt.format;
1512		m_dataType	= fmt.dataType;
1513	}
1514
1515protected:
1516	void createTexture (void)
1517	{
1518		deUint32			tex			= 0;
1519		tcu::TextureLevel	data		(m_texFormat);
1520		de::Random			rnd			(deStringHash(getName()));
1521
1522		glGenTextures(1, &tex);
1523		glBindTexture(GL_TEXTURE_2D, tex);
1524		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1525
1526		// First allocate storage for each level.
1527		for (int ndx = 0; ndx < m_numLevels; ndx++)
1528		{
1529			int		levelW		= de::max(1, m_width >> ndx);
1530			int		levelH		= de::max(1, m_height >> ndx);
1531
1532			glTexImage2D(GL_TEXTURE_2D, ndx, m_internalFormat, levelW, levelH, 0, m_format, m_dataType, DE_NULL);
1533		}
1534
1535		// Specify pixel data to all levels using glTexSubImage2D()
1536		for (int ndx = 0; ndx < m_numLevels; ndx++)
1537		{
1538			int		levelW		= de::max(1, m_width >> ndx);
1539			int		levelH		= de::max(1, m_height >> ndx);
1540			Vec4	gMin		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1541			Vec4	gMax		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1542
1543			data.setSize(levelW, levelH);
1544			tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
1545
1546			glTexSubImage2D(GL_TEXTURE_2D, ndx, 0, 0, levelW, levelH, m_format, m_dataType, data.getAccess().getDataPtr());
1547		}
1548	}
1549
1550	deUint32	m_internalFormat;
1551	deUint32	m_format;
1552	deUint32	m_dataType;
1553};
1554
1555// TexSubImage2D() to empty cubemap texture
1556class TexSubImageCubeEmptyTexCase : public TextureCubeSpecCase
1557{
1558public:
1559	TexSubImageCubeEmptyTexCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, int size)
1560		: TextureCubeSpecCase	(context, name, desc, glu::mapGLTransferFormat(format, dataType), size, deLog2Floor32(size)+1)
1561		, m_internalFormat		(format)
1562		, m_format				(format)
1563		, m_dataType			(dataType)
1564	{
1565	}
1566
1567	TexSubImageCubeEmptyTexCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int size)
1568		: TextureCubeSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, deLog2Floor32(size)+1)
1569		, m_internalFormat		(internalFormat)
1570		, m_format				(GL_NONE)
1571		, m_dataType			(GL_NONE)
1572	{
1573		glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
1574		m_format	= fmt.format;
1575		m_dataType	= fmt.dataType;
1576	}
1577
1578protected:
1579	void createTexture (void)
1580	{
1581		deUint32			tex			= 0;
1582		tcu::TextureLevel	data		(m_texFormat);
1583		de::Random			rnd			(deStringHash(getName()));
1584
1585		glGenTextures(1, &tex);
1586		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1587		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1588
1589		// Specify storage for each level.
1590		for (int ndx = 0; ndx < m_numLevels; ndx++)
1591		{
1592			int levelSize = de::max(1, m_size >> ndx);
1593
1594			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1595				glTexImage2D(s_cubeMapFaces[face], ndx, m_internalFormat, levelSize, levelSize, 0, m_format, m_dataType, DE_NULL);
1596		}
1597
1598		// Specify data using glTexSubImage2D()
1599		for (int ndx = 0; ndx < m_numLevels; ndx++)
1600		{
1601			int levelSize = de::max(1, m_size >> ndx);
1602
1603			data.setSize(levelSize, levelSize);
1604
1605			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1606			{
1607				Vec4 gMin = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1608				Vec4 gMax = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1609
1610				tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
1611
1612				glTexSubImage2D(s_cubeMapFaces[face], ndx, 0, 0, levelSize, levelSize, m_format, m_dataType, data.getAccess().getDataPtr());
1613			}
1614		}
1615	}
1616
1617	deUint32	m_internalFormat;
1618	deUint32	m_format;
1619	deUint32	m_dataType;
1620};
1621
1622// TexSubImage2D() unpack alignment with 2D texture
1623class TexSubImage2DAlignCase : public Texture2DSpecCase
1624{
1625public:
1626	TexSubImage2DAlignCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, int width, int height, int subX, int subY, int subW, int subH, int alignment)
1627		: Texture2DSpecCase	(context, name, desc, glu::mapGLTransferFormat(format, dataType), width, height, 1)
1628		, m_internalFormat	(format)
1629		, m_format			(format)
1630		, m_dataType		(dataType)
1631		, m_subX			(subX)
1632		, m_subY			(subY)
1633		, m_subW			(subW)
1634		, m_subH			(subH)
1635		, m_alignment		(alignment)
1636	{
1637	}
1638
1639	TexSubImage2DAlignCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int width, int height, int subX, int subY, int subW, int subH, int alignment)
1640		: Texture2DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, 1)
1641		, m_internalFormat	(internalFormat)
1642		, m_format			(GL_NONE)
1643		, m_dataType		(GL_NONE)
1644		, m_subX			(subX)
1645		, m_subY			(subY)
1646		, m_subW			(subW)
1647		, m_subH			(subH)
1648		, m_alignment		(alignment)
1649	{
1650		glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
1651		m_format	= fmt.format;
1652		m_dataType	= fmt.dataType;
1653	}
1654
1655protected:
1656	void createTexture (void)
1657	{
1658		deUint32			tex			= 0;
1659		vector<deUint8>		data;
1660
1661		glGenTextures(1, &tex);
1662		glBindTexture(GL_TEXTURE_2D, tex);
1663
1664		// Specify base level.
1665		data.resize(m_texFormat.getPixelSize()*m_width*m_height);
1666		tcu::fillWithComponentGradients(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, 1, &data[0]), Vec4(0.0f), Vec4(1.0f));
1667
1668		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1669		glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, m_format, m_dataType, &data[0]);
1670
1671		// Re-specify subrectangle.
1672		int rowPitch = deAlign32(m_texFormat.getPixelSize()*m_subW, m_alignment);
1673		data.resize(rowPitch*m_subH);
1674		tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_subW, m_subH, 1, rowPitch, 0, &data[0]), 4, Vec4(1.0f, 0.0f, 0.0f, 1.0f), Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1675
1676		glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
1677		glTexSubImage2D(GL_TEXTURE_2D, 0, m_subX, m_subY, m_subW, m_subH, m_format, m_dataType, &data[0]);
1678	}
1679
1680	deUint32	m_internalFormat;
1681	deUint32	m_format;
1682	deUint32	m_dataType;
1683	int			m_subX;
1684	int			m_subY;
1685	int			m_subW;
1686	int			m_subH;
1687	int			m_alignment;
1688};
1689
1690// TexSubImage2D() unpack alignment with cubemap texture
1691class TexSubImageCubeAlignCase : public TextureCubeSpecCase
1692{
1693public:
1694	TexSubImageCubeAlignCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, int size, int subX, int subY, int subW, int subH, int alignment)
1695		: TextureCubeSpecCase	(context, name, desc, glu::mapGLTransferFormat(format, dataType), size, 1)
1696		, m_internalFormat		(format)
1697		, m_format				(format)
1698		, m_dataType			(dataType)
1699		, m_subX				(subX)
1700		, m_subY				(subY)
1701		, m_subW				(subW)
1702		, m_subH				(subH)
1703		, m_alignment			(alignment)
1704	{
1705	}
1706
1707	TexSubImageCubeAlignCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int size, int subX, int subY, int subW, int subH, int alignment)
1708		: TextureCubeSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, 1)
1709		, m_internalFormat		(internalFormat)
1710		, m_format				(GL_NONE)
1711		, m_dataType			(GL_NONE)
1712		, m_subX				(subX)
1713		, m_subY				(subY)
1714		, m_subW				(subW)
1715		, m_subH				(subH)
1716		, m_alignment			(alignment)
1717	{
1718		glu::TransferFormat fmt = glu::getTransferFormat(m_texFormat);
1719		m_format	= fmt.format;
1720		m_dataType	= fmt.dataType;
1721	}
1722
1723protected:
1724	void createTexture (void)
1725	{
1726		deUint32			tex			= 0;
1727		vector<deUint8>		data;
1728
1729		glGenTextures(1, &tex);
1730		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1731
1732		// Specify base level.
1733		data.resize(m_texFormat.getPixelSize()*m_size*m_size);
1734		tcu::fillWithComponentGradients(tcu::PixelBufferAccess(m_texFormat, m_size, m_size, 1, &data[0]), Vec4(0.0f), Vec4(1.0f));
1735
1736		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1737		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
1738			glTexImage2D(s_cubeMapFaces[face], 0, m_internalFormat, m_size, m_size, 0, m_format, m_dataType, &data[0]);
1739
1740		// Re-specify subrectangle.
1741		int rowPitch = deAlign32(m_texFormat.getPixelSize()*m_subW, m_alignment);
1742		data.resize(rowPitch*m_subH);
1743		tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_subW, m_subH, 1, rowPitch, 0, &data[0]), 4, Vec4(1.0f, 0.0f, 0.0f, 1.0f), Vec4(0.0f, 1.0f, 0.0f, 1.0f));
1744
1745		glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
1746		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
1747			glTexSubImage2D(s_cubeMapFaces[face], 0, m_subX, m_subY, m_subW, m_subH, m_format, m_dataType, &data[0]);
1748	}
1749
1750	deUint32	m_internalFormat;
1751	deUint32	m_format;
1752	deUint32	m_dataType;
1753	int			m_subX;
1754	int			m_subY;
1755	int			m_subW;
1756	int			m_subH;
1757	int			m_alignment;
1758};
1759
1760// TexSubImage3D() unpack parameters case.
1761class TexSubImage3DParamsCase : public Texture3DSpecCase
1762{
1763public:
1764	TexSubImage3DParamsCase (Context&		context,
1765							 const char*	name,
1766							 const char*	desc,
1767							 deUint32		internalFormat,
1768							 int			width,
1769							 int			height,
1770							 int			depth,
1771							 int			subX,
1772							 int			subY,
1773							 int			subZ,
1774							 int			subW,
1775							 int			subH,
1776							 int			subD,
1777							 int			imageHeight,
1778							 int			rowLength,
1779							 int			skipImages,
1780							 int			skipRows,
1781							 int			skipPixels,
1782							 int			alignment)
1783		: Texture3DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth, 1)
1784		, m_internalFormat	(internalFormat)
1785		, m_subX			(subX)
1786		, m_subY			(subY)
1787		, m_subZ			(subZ)
1788		, m_subW			(subW)
1789		, m_subH			(subH)
1790		, m_subD			(subD)
1791		, m_imageHeight		(imageHeight)
1792		, m_rowLength		(rowLength)
1793		, m_skipImages		(skipImages)
1794		, m_skipRows		(skipRows)
1795		, m_skipPixels		(skipPixels)
1796		, m_alignment		(alignment)
1797	{
1798	}
1799
1800protected:
1801	void createTexture (void)
1802	{
1803		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
1804		int						pixelSize		= m_texFormat.getPixelSize();
1805		deUint32				tex				= 0;
1806		vector<deUint8>			data;
1807
1808		DE_ASSERT(m_numLevels == 1);
1809
1810		glGenTextures(1, &tex);
1811		glBindTexture(GL_TEXTURE_3D, tex);
1812
1813		// Fill with gradient.
1814		{
1815			int		rowPitch		= deAlign32(pixelSize*m_width,  4);
1816			int		slicePitch		= rowPitch*m_height;
1817
1818			data.resize(slicePitch*m_depth);
1819			tcu::fillWithComponentGradients(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, m_depth, rowPitch, slicePitch, &data[0]), m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
1820		}
1821
1822		glTexImage3D(GL_TEXTURE_3D, 0, m_internalFormat, m_width, m_height, m_depth, 0, transferFmt.format, transferFmt.dataType, &data[0]);
1823
1824		// Fill data with grid.
1825		{
1826			int		rowLength		= m_rowLength > 0 ? m_rowLength : m_subW;
1827			int		rowPitch		= deAlign32(rowLength*pixelSize, m_alignment);
1828			int		imageHeight		= m_imageHeight > 0 ? m_imageHeight : m_subH;
1829			int		slicePitch		= imageHeight*rowPitch;
1830			Vec4	cScale			= m_texFormatInfo.valueMax-m_texFormatInfo.valueMin;
1831			Vec4	cBias			= m_texFormatInfo.valueMin;
1832			Vec4	colorA			= Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
1833			Vec4	colorB			= Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias;
1834
1835			data.resize(slicePitch*(m_depth+m_skipImages));
1836			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), 4, colorA, colorB);
1837		}
1838
1839		glPixelStorei(GL_UNPACK_IMAGE_HEIGHT,	m_imageHeight);
1840		glPixelStorei(GL_UNPACK_ROW_LENGTH,		m_rowLength);
1841		glPixelStorei(GL_UNPACK_SKIP_IMAGES,	m_skipImages);
1842		glPixelStorei(GL_UNPACK_SKIP_ROWS,		m_skipRows);
1843		glPixelStorei(GL_UNPACK_SKIP_PIXELS,	m_skipPixels);
1844		glPixelStorei(GL_UNPACK_ALIGNMENT,		m_alignment);
1845		glTexSubImage3D(GL_TEXTURE_3D, 0, m_subX, m_subY, m_subZ, m_subW, m_subH, m_subD, transferFmt.format, transferFmt.dataType, &data[0]);
1846	}
1847
1848	deUint32	m_internalFormat;
1849	int			m_subX;
1850	int			m_subY;
1851	int			m_subZ;
1852	int			m_subW;
1853	int			m_subH;
1854	int			m_subD;
1855	int			m_imageHeight;
1856	int			m_rowLength;
1857	int			m_skipImages;
1858	int			m_skipRows;
1859	int			m_skipPixels;
1860	int			m_alignment;
1861};
1862
1863// Basic CopyTexImage2D() with 2D texture usage
1864class BasicCopyTexImage2DCase : public Texture2DSpecCase
1865{
1866public:
1867	BasicCopyTexImage2DCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int width, int height)
1868		: Texture2DSpecCase	(context, name, desc, glu::mapGLTransferFormat(internalFormat, GL_UNSIGNED_BYTE), width, height, maxLevelCount(width, height))
1869		, m_internalFormat	(internalFormat)
1870	{
1871	}
1872
1873protected:
1874	void createTexture (void)
1875	{
1876		const tcu::RenderTarget&	renderTarget	= TestCase::m_context.getRenderContext().getRenderTarget();
1877		bool						targetHasRGB	= renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 && renderTarget.getPixelFormat().blueBits > 0;
1878		bool						targetHasAlpha	= renderTarget.getPixelFormat().alphaBits > 0;
1879		tcu::TextureFormat			fmt				= mapGLUnsizedInternalFormat(m_internalFormat);
1880		bool						texHasRGB		= fmt.order != tcu::TextureFormat::A;
1881		bool						texHasAlpha		= fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA || fmt.order == tcu::TextureFormat::A;
1882		deUint32					tex				= 0;
1883		de::Random					rnd				(deStringHash(getName()));
1884		GradientShader				shader			(glu::TYPE_FLOAT_VEC4);
1885		deUint32					shaderID		= getCurrentContext()->createProgram(&shader);
1886
1887		if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
1888			throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__);
1889
1890		// Fill render target with gradient.
1891		shader.setGradient(*getCurrentContext(), shaderID, Vec4(0.0f), Vec4(1.0f));
1892		sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f));
1893
1894		glGenTextures(1, &tex);
1895		glBindTexture(GL_TEXTURE_2D, tex);
1896
1897		for (int ndx = 0; ndx < m_numLevels; ndx++)
1898		{
1899			int		levelW		= de::max(1, m_width >> ndx);
1900			int		levelH		= de::max(1, m_height >> ndx);
1901			int		x			= rnd.getInt(0, getWidth()	- levelW);
1902			int		y			= rnd.getInt(0, getHeight()	- levelH);
1903
1904			glCopyTexImage2D(GL_TEXTURE_2D, ndx, m_internalFormat, x, y, levelW, levelH, 0);
1905		}
1906	}
1907
1908	deUint32 m_internalFormat;
1909};
1910
1911// Basic CopyTexImage2D() with cubemap usage
1912class BasicCopyTexImageCubeCase : public TextureCubeSpecCase
1913{
1914public:
1915	BasicCopyTexImageCubeCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int size)
1916		: TextureCubeSpecCase	(context, name, desc, glu::mapGLTransferFormat(internalFormat, GL_UNSIGNED_BYTE), size, deLog2Floor32(size)+1)
1917		, m_internalFormat		(internalFormat)
1918	{
1919	}
1920
1921protected:
1922	void createTexture (void)
1923	{
1924		const tcu::RenderTarget&	renderTarget	= TestCase::m_context.getRenderContext().getRenderTarget();
1925		bool						targetHasRGB	= renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 && renderTarget.getPixelFormat().blueBits > 0;
1926		bool						targetHasAlpha	= renderTarget.getPixelFormat().alphaBits > 0;
1927		tcu::TextureFormat			fmt				= mapGLUnsizedInternalFormat(m_internalFormat);
1928		bool						texHasRGB		= fmt.order != tcu::TextureFormat::A;
1929		bool						texHasAlpha		= fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA || fmt.order == tcu::TextureFormat::A;
1930		deUint32					tex				= 0;
1931		de::Random					rnd				(deStringHash(getName()));
1932		GradientShader				shader			(glu::TYPE_FLOAT_VEC4);
1933		deUint32					shaderID		= getCurrentContext()->createProgram(&shader);
1934
1935		if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
1936			throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__);
1937
1938		// Fill render target with gradient.
1939		shader.setGradient(*getCurrentContext(), shaderID, Vec4(0.0f), Vec4(1.0f));
1940		sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f));
1941
1942		glGenTextures(1, &tex);
1943		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1944
1945		for (int ndx = 0; ndx < m_numLevels; ndx++)
1946		{
1947			int levelSize = de::max(1, m_size >> ndx);
1948
1949			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1950			{
1951				int x = rnd.getInt(0, getWidth()	- levelSize);
1952				int y = rnd.getInt(0, getHeight()	- levelSize);
1953
1954				glCopyTexImage2D(s_cubeMapFaces[face], ndx, m_internalFormat, x, y, levelSize, levelSize, 0);
1955			}
1956		}
1957	}
1958
1959	deUint32 m_internalFormat;
1960};
1961
1962// Basic CopyTexSubImage2D() with 2D texture usage
1963class BasicCopyTexSubImage2DCase : public Texture2DSpecCase
1964{
1965public:
1966	BasicCopyTexSubImage2DCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, int width, int height)
1967		: Texture2DSpecCase	(context, name, desc, glu::mapGLTransferFormat(format, dataType), width, height, maxLevelCount(width, height))
1968		, m_format			(format)
1969		, m_dataType		(dataType)
1970	{
1971	}
1972
1973protected:
1974	void createTexture (void)
1975	{
1976		const tcu::RenderTarget&	renderTarget	= TestCase::m_context.getRenderContext().getRenderTarget();
1977		bool						targetHasRGB	= renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 && renderTarget.getPixelFormat().blueBits > 0;
1978		bool						targetHasAlpha	= renderTarget.getPixelFormat().alphaBits > 0;
1979		tcu::TextureFormat			fmt				= glu::mapGLTransferFormat(m_format, m_dataType);
1980		bool						texHasRGB		= fmt.order != tcu::TextureFormat::A;
1981		bool						texHasAlpha		= fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA || fmt.order == tcu::TextureFormat::A;
1982		deUint32					tex				= 0;
1983		tcu::TextureLevel			data			(fmt);
1984		de::Random					rnd				(deStringHash(getName()));
1985		GradientShader				shader			(glu::TYPE_FLOAT_VEC4);
1986		deUint32					shaderID		= getCurrentContext()->createProgram(&shader);
1987
1988		if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
1989			throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__);
1990
1991		glGenTextures(1, &tex);
1992		glBindTexture(GL_TEXTURE_2D, tex);
1993		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1994
1995		// First specify full texture.
1996		for (int ndx = 0; ndx < m_numLevels; ndx++)
1997		{
1998			int		levelW		= de::max(1, m_width >> ndx);
1999			int		levelH		= de::max(1, m_height >> ndx);
2000
2001			Vec4	colorA		= randomVector<4>(rnd);
2002			Vec4	colorB		= randomVector<4>(rnd);
2003			int		cellSize	= rnd.getInt(2, 16);
2004
2005			data.setSize(levelW, levelH);
2006			tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
2007
2008			glTexImage2D(GL_TEXTURE_2D, ndx, m_format, levelW, levelH, 0, m_format, m_dataType, data.getAccess().getDataPtr());
2009		}
2010
2011		// Fill render target with gradient.
2012		shader.setGradient(*getCurrentContext(), shaderID, Vec4(0.0f), Vec4(1.0f));
2013		sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f));
2014
2015		// Re-specify parts of each level.
2016		for (int ndx = 0; ndx < m_numLevels; ndx++)
2017		{
2018			int		levelW		= de::max(1, m_width >> ndx);
2019			int		levelH		= de::max(1, m_height >> ndx);
2020
2021			int		w			= rnd.getInt(1, levelW);
2022			int		h			= rnd.getInt(1, levelH);
2023			int		xo			= rnd.getInt(0, levelW-w);
2024			int		yo			= rnd.getInt(0, levelH-h);
2025
2026			int		x			= rnd.getInt(0, getWidth() - w);
2027			int		y			= rnd.getInt(0, getHeight() - h);
2028
2029			glCopyTexSubImage2D(GL_TEXTURE_2D, ndx, xo, yo, x, y, w, h);
2030		}
2031	}
2032
2033	deUint32	m_format;
2034	deUint32	m_dataType;
2035};
2036
2037// Basic CopyTexSubImage2D() with cubemap usage
2038class BasicCopyTexSubImageCubeCase : public TextureCubeSpecCase
2039{
2040public:
2041	BasicCopyTexSubImageCubeCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, int size)
2042		: TextureCubeSpecCase	(context, name, desc, glu::mapGLTransferFormat(format, dataType), size, deLog2Floor32(size)+1)
2043		, m_format				(format)
2044		, m_dataType			(dataType)
2045	{
2046	}
2047
2048protected:
2049	void createTexture (void)
2050	{
2051		const tcu::RenderTarget&	renderTarget	= TestCase::m_context.getRenderContext().getRenderTarget();
2052		bool						targetHasRGB	= renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 && renderTarget.getPixelFormat().blueBits > 0;
2053		bool						targetHasAlpha	= renderTarget.getPixelFormat().alphaBits > 0;
2054		tcu::TextureFormat			fmt				= glu::mapGLTransferFormat(m_format, m_dataType);
2055		bool						texHasRGB		= fmt.order != tcu::TextureFormat::A;
2056		bool						texHasAlpha		= fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA || fmt.order == tcu::TextureFormat::A;
2057		deUint32					tex				= 0;
2058		tcu::TextureLevel			data			(fmt);
2059		de::Random					rnd				(deStringHash(getName()));
2060		GradientShader				shader			(glu::TYPE_FLOAT_VEC4);
2061		deUint32					shaderID		= getCurrentContext()->createProgram(&shader);
2062
2063		if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
2064			throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__);
2065
2066		glGenTextures(1, &tex);
2067		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
2068		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2069
2070		for (int ndx = 0; ndx < m_numLevels; ndx++)
2071		{
2072			int levelSize = de::max(1, m_size >> ndx);
2073
2074			data.setSize(levelSize, levelSize);
2075
2076			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
2077			{
2078				Vec4	colorA		= randomVector<4>(rnd);
2079				Vec4	colorB		= randomVector<4>(rnd);
2080				int		cellSize	= rnd.getInt(2, 16);
2081
2082				tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
2083				glTexImage2D(s_cubeMapFaces[face], ndx, m_format, levelSize, levelSize, 0, m_format, m_dataType, data.getAccess().getDataPtr());
2084			}
2085		}
2086
2087		// Fill render target with gradient.
2088		shader.setGradient(*getCurrentContext(), shaderID, Vec4(0.0f), Vec4(1.0f));
2089		sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f));
2090
2091		// Re-specify parts of each face and level.
2092		for (int ndx = 0; ndx < m_numLevels; ndx++)
2093		{
2094			int levelSize = de::max(1, m_size >> ndx);
2095
2096			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
2097			{
2098				int		w			= rnd.getInt(1, levelSize);
2099				int		h			= rnd.getInt(1, levelSize);
2100				int		xo			= rnd.getInt(0, levelSize-w);
2101				int		yo			= rnd.getInt(0, levelSize-h);
2102
2103				int		x			= rnd.getInt(0, getWidth() - w);
2104				int		y			= rnd.getInt(0, getHeight() - h);
2105
2106				glCopyTexSubImage2D(s_cubeMapFaces[face], ndx, xo, yo, x, y, w, h);
2107			}
2108		}
2109	}
2110
2111	deUint32	m_format;
2112	deUint32	m_dataType;
2113};
2114
2115// Basic glTexStorage2D() with 2D texture usage
2116class BasicTexStorage2DCase : public Texture2DSpecCase
2117{
2118public:
2119	BasicTexStorage2DCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int width, int height, int numLevels)
2120		: Texture2DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, numLevels)
2121		, m_internalFormat	(internalFormat)
2122	{
2123	}
2124
2125protected:
2126	void createTexture (void)
2127	{
2128		tcu::TextureFormat		fmt				= glu::mapGLInternalFormat(m_internalFormat);
2129		glu::TransferFormat		transferFmt		= glu::getTransferFormat(fmt);
2130		deUint32				tex				= 0;
2131		tcu::TextureLevel		levelData		(fmt);
2132		de::Random				rnd				(deStringHash(getName()));
2133
2134		glGenTextures(1, &tex);
2135		glBindTexture(GL_TEXTURE_2D, tex);
2136		glTexStorage2D(GL_TEXTURE_2D, m_numLevels, m_internalFormat, m_width, m_height);
2137
2138		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2139
2140		for (int ndx = 0; ndx < m_numLevels; ndx++)
2141		{
2142			int		levelW		= de::max(1, m_width >> ndx);
2143			int		levelH		= de::max(1, m_height >> ndx);
2144			Vec4	gMin		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2145			Vec4	gMax		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2146
2147			levelData.setSize(levelW, levelH);
2148			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
2149
2150			glTexSubImage2D(GL_TEXTURE_2D, ndx, 0, 0, levelW, levelH, transferFmt.format, transferFmt.dataType, levelData.getAccess().getDataPtr());
2151		}
2152	}
2153
2154	deUint32 m_internalFormat;
2155};
2156
2157// Basic glTexStorage2D() with cubemap usage
2158class BasicTexStorageCubeCase : public TextureCubeSpecCase
2159{
2160public:
2161	BasicTexStorageCubeCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int size, int numLevels)
2162		: TextureCubeSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, numLevels)
2163		, m_internalFormat		(internalFormat)
2164	{
2165	}
2166
2167protected:
2168	void createTexture (void)
2169	{
2170		tcu::TextureFormat		fmt				= glu::mapGLInternalFormat(m_internalFormat);
2171		glu::TransferFormat		transferFmt		= glu::getTransferFormat(fmt);
2172		deUint32				tex				= 0;
2173		tcu::TextureLevel		levelData		(fmt);
2174		de::Random				rnd				(deStringHash(getName()));
2175
2176		glGenTextures(1, &tex);
2177		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
2178		glTexStorage2D(GL_TEXTURE_CUBE_MAP, m_numLevels, m_internalFormat, m_size, m_size);
2179
2180		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2181
2182		for (int ndx = 0; ndx < m_numLevels; ndx++)
2183		{
2184			int levelSize = de::max(1, m_size >> ndx);
2185
2186			levelData.setSize(levelSize, levelSize);
2187
2188			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
2189			{
2190				Vec4 gMin = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2191				Vec4 gMax = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2192
2193				tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
2194
2195				glTexSubImage2D(s_cubeMapFaces[face], ndx, 0, 0, levelSize, levelSize, transferFmt.format, transferFmt.dataType, levelData.getAccess().getDataPtr());
2196			}
2197		}
2198	}
2199
2200	deUint32 m_internalFormat;
2201};
2202
2203// Basic glTexStorage3D() with 2D array texture usage
2204class BasicTexStorage2DArrayCase : public Texture2DArraySpecCase
2205{
2206public:
2207	BasicTexStorage2DArrayCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int width, int height, int numLayers, int numLevels)
2208		: Texture2DArraySpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, numLayers, numLevels)
2209		, m_internalFormat			(internalFormat)
2210	{
2211	}
2212
2213protected:
2214	void createTexture (void)
2215	{
2216		deUint32				tex			= 0;
2217		tcu::TextureLevel		levelData	(m_texFormat);
2218		de::Random				rnd			(deStringHash(getName()));
2219		glu::TransferFormat		transferFmt	= glu::getTransferFormat(m_texFormat);
2220
2221		glGenTextures	(1, &tex);
2222		glBindTexture	(GL_TEXTURE_2D_ARRAY, tex);
2223		glTexStorage3D	(GL_TEXTURE_2D_ARRAY, m_numLevels, m_internalFormat, m_width, m_height, m_numLayers);
2224
2225		glPixelStorei	(GL_UNPACK_ALIGNMENT, 1);
2226
2227		for (int ndx = 0; ndx < m_numLevels; ndx++)
2228		{
2229			int		levelW		= de::max(1, m_width	>> ndx);
2230			int		levelH		= de::max(1, m_height	>> ndx);
2231			Vec4	gMin		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2232			Vec4	gMax		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2233
2234			levelData.setSize(levelW, levelH, m_numLayers);
2235			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
2236
2237			glTexSubImage3D(GL_TEXTURE_2D_ARRAY, ndx, 0, 0, 0, levelW, levelH, m_numLayers, transferFmt.format, transferFmt.dataType, levelData.getAccess().getDataPtr());
2238		}
2239	}
2240
2241	deUint32 m_internalFormat;
2242};
2243
2244// Basic TexStorage3D() with 3D texture usage
2245class BasicTexStorage3DCase : public Texture3DSpecCase
2246{
2247public:
2248	BasicTexStorage3DCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, int width, int height, int depth, int numLevels)
2249		: Texture3DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth, numLevels)
2250		, m_internalFormat	(internalFormat)
2251	{
2252	}
2253
2254protected:
2255	void createTexture (void)
2256	{
2257		deUint32				tex			= 0;
2258		tcu::TextureLevel		levelData	(m_texFormat);
2259		de::Random				rnd			(deStringHash(getName()));
2260		glu::TransferFormat		transferFmt	= glu::getTransferFormat(m_texFormat);
2261
2262		glGenTextures	(1, &tex);
2263		glBindTexture	(GL_TEXTURE_3D, tex);
2264		glTexStorage3D	(GL_TEXTURE_3D, m_numLevels, m_internalFormat, m_width, m_height, m_depth);
2265
2266		glPixelStorei	(GL_UNPACK_ALIGNMENT, 1);
2267
2268		for (int ndx = 0; ndx < m_numLevels; ndx++)
2269		{
2270			int		levelW		= de::max(1, m_width	>> ndx);
2271			int		levelH		= de::max(1, m_height	>> ndx);
2272			int		levelD		= de::max(1, m_depth	>> ndx);
2273			Vec4	gMin		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2274			Vec4	gMax		= randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2275
2276			levelData.setSize(levelW, levelH, levelD);
2277			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
2278
2279			glTexSubImage3D(GL_TEXTURE_3D, ndx, 0, 0, 0, levelW, levelH, levelD, transferFmt.format, transferFmt.dataType, levelData.getAccess().getDataPtr());
2280		}
2281	}
2282
2283	deUint32 m_internalFormat;
2284};
2285
2286// Pixel buffer object cases.
2287
2288// TexImage2D() from pixel buffer object.
2289class TexImage2DBufferCase : public Texture2DSpecCase
2290{
2291public:
2292	TexImage2DBufferCase (Context&		context,
2293						  const char*	name,
2294						  const char*	desc,
2295						  deUint32		internalFormat,
2296						  int			width,
2297						  int			height,
2298						  int			rowLength,
2299						  int			skipRows,
2300						  int			skipPixels,
2301						  int			alignment,
2302						  int			offset)
2303		: Texture2DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, 1)
2304		, m_internalFormat	(internalFormat)
2305		, m_rowLength		(rowLength)
2306		, m_skipRows		(skipRows)
2307		, m_skipPixels		(skipPixels)
2308		, m_alignment		(alignment)
2309		, m_offset			(offset)
2310	{
2311	}
2312
2313protected:
2314	void createTexture (void)
2315	{
2316		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
2317		int						pixelSize		= m_texFormat.getPixelSize();
2318		int						rowLength		= m_rowLength > 0 ? m_rowLength : m_width + m_skipPixels;
2319		int						rowPitch		= deAlign32(rowLength*pixelSize, m_alignment);
2320		int						height			= m_height + m_skipRows;
2321		deUint32				buf				= 0;
2322		deUint32				tex				= 0;
2323		vector<deUint8>			data;
2324
2325		DE_ASSERT(m_numLevels == 1);
2326
2327		// Fill data with grid.
2328		data.resize(rowPitch*height + m_offset);
2329		{
2330			Vec4	cScale		= m_texFormatInfo.valueMax-m_texFormatInfo.valueMin;
2331			Vec4	cBias		= m_texFormatInfo.valueMin;
2332			Vec4	colorA		= Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
2333			Vec4	colorB		= Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias;
2334
2335			tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, 1, rowPitch, 0, &data[0] + m_skipRows*rowPitch + m_skipPixels*pixelSize + m_offset), 4, colorA, colorB);
2336		}
2337
2338		// Create buffer and upload.
2339		glGenBuffers(1, &buf);
2340		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
2341		glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
2342
2343		glPixelStorei(GL_UNPACK_ROW_LENGTH,		m_rowLength);
2344		glPixelStorei(GL_UNPACK_SKIP_ROWS,		m_skipRows);
2345		glPixelStorei(GL_UNPACK_SKIP_PIXELS,	m_skipPixels);
2346		glPixelStorei(GL_UNPACK_ALIGNMENT,		m_alignment);
2347
2348		glGenTextures(1, &tex);
2349		glBindTexture(GL_TEXTURE_2D, tex);
2350		glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, transferFmt.format, transferFmt.dataType, (const void*)(deUintptr)m_offset);
2351	}
2352
2353	deUint32	m_internalFormat;
2354	int			m_rowLength;
2355	int			m_skipRows;
2356	int			m_skipPixels;
2357	int			m_alignment;
2358	int			m_offset;
2359};
2360
2361// TexImage2D() cubemap from pixel buffer object case
2362class TexImageCubeBufferCase : public TextureCubeSpecCase
2363{
2364public:
2365	TexImageCubeBufferCase (Context&	context,
2366							const char*	name,
2367							const char*	desc,
2368							deUint32	internalFormat,
2369							int			size,
2370							int			rowLength,
2371							int			skipRows,
2372							int			skipPixels,
2373							int			alignment,
2374							int			offset)
2375		: TextureCubeSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, 1)
2376		, m_internalFormat		(internalFormat)
2377		, m_rowLength			(rowLength)
2378		, m_skipRows			(skipRows)
2379		, m_skipPixels			(skipPixels)
2380		, m_alignment			(alignment)
2381		, m_offset				(offset)
2382	{
2383	}
2384
2385protected:
2386	void createTexture (void)
2387	{
2388		de::Random					rnd			(deStringHash(getName()));
2389		deUint32					tex			= 0;
2390		glu::TransferFormat			fmt			= glu::getTransferFormat(m_texFormat);
2391		const int					pixelSize	= m_texFormat.getPixelSize();
2392		const int					rowLength	= m_rowLength > 0 ? m_rowLength : m_size + m_skipPixels;
2393		const int					rowPitch	= deAlign32(rowLength*pixelSize, m_alignment);
2394		const int					height		= m_size + m_skipRows;
2395		vector<vector<deUint8> >	data		(DE_LENGTH_OF_ARRAY(s_cubeMapFaces));
2396
2397		DE_ASSERT(m_numLevels == 1);
2398
2399		glGenTextures(1, &tex);
2400		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
2401		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2402
2403		for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
2404		{
2405			deUint32 buf = 0;
2406
2407			{
2408				const Vec4 gMin = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2409				const Vec4 gMax = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2410
2411				data[face].resize(rowPitch*height + m_offset);
2412				tcu::fillWithComponentGradients(tcu::PixelBufferAccess(m_texFormat, m_size, m_size, 1, rowPitch, 0, &data[face][0] + m_skipRows*rowPitch + m_skipPixels*pixelSize + m_offset), gMin, gMax);
2413			}
2414
2415			// Create buffer and upload.
2416			glGenBuffers(1, &buf);
2417			glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
2418			glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data[face].size(), &data[face][0], GL_STATIC_DRAW);
2419
2420			glPixelStorei(GL_UNPACK_ROW_LENGTH,		m_rowLength);
2421			glPixelStorei(GL_UNPACK_SKIP_ROWS,		m_skipRows);
2422			glPixelStorei(GL_UNPACK_SKIP_PIXELS,	m_skipPixels);
2423			glPixelStorei(GL_UNPACK_ALIGNMENT,		m_alignment);
2424
2425			glTexImage2D(s_cubeMapFaces[face], 0, m_internalFormat, m_size, m_size, 0, fmt.format, fmt.dataType, (const void*)(deUintptr)m_offset);
2426		}
2427	}
2428
2429	deUint32	m_internalFormat;
2430	int			m_rowLength;
2431	int			m_skipRows;
2432	int			m_skipPixels;
2433	int			m_alignment;
2434	int			m_offset;
2435};
2436
2437// TexImage3D() 2D array from pixel buffer object.
2438class TexImage2DArrayBufferCase : public Texture2DArraySpecCase
2439{
2440public:
2441	TexImage2DArrayBufferCase (Context&		context,
2442							   const char*	name,
2443							   const char*	desc,
2444							   deUint32		internalFormat,
2445							   int			width,
2446							   int			height,
2447							   int			depth,
2448							   int			imageHeight,
2449							   int			rowLength,
2450							   int			skipImages,
2451							   int			skipRows,
2452							   int			skipPixels,
2453							   int			alignment,
2454							   int			offset)
2455		: Texture2DArraySpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth, 1)
2456		, m_internalFormat			(internalFormat)
2457		, m_imageHeight				(imageHeight)
2458		, m_rowLength				(rowLength)
2459		, m_skipImages				(skipImages)
2460		, m_skipRows				(skipRows)
2461		, m_skipPixels				(skipPixels)
2462		, m_alignment				(alignment)
2463		, m_offset					(offset)
2464	{
2465	}
2466
2467protected:
2468	void createTexture (void)
2469	{
2470		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
2471		int						pixelSize		= m_texFormat.getPixelSize();
2472		int						rowLength		= m_rowLength > 0 ? m_rowLength : m_width;
2473		int						rowPitch		= deAlign32(rowLength*pixelSize, m_alignment);
2474		int						imageHeight		= m_imageHeight > 0 ? m_imageHeight : m_height;
2475		int						slicePitch		= imageHeight*rowPitch;
2476		deUint32				tex				= 0;
2477		deUint32				buf				= 0;
2478		vector<deUint8>			data;
2479
2480		DE_ASSERT(m_numLevels == 1);
2481
2482		// Fill data with grid.
2483		data.resize(slicePitch*(m_numLayers+m_skipImages) + m_offset);
2484		{
2485			Vec4	cScale		= m_texFormatInfo.valueMax-m_texFormatInfo.valueMin;
2486			Vec4	cBias		= m_texFormatInfo.valueMin;
2487			Vec4	colorA		= Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
2488			Vec4	colorB		= Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias;
2489
2490			tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, m_numLayers, rowPitch, slicePitch, &data[0] + m_skipImages*slicePitch + m_skipRows*rowPitch + m_skipPixels*pixelSize + m_offset), 4, colorA, colorB);
2491		}
2492
2493		glGenBuffers(1, &buf);
2494		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
2495		glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
2496
2497		glPixelStorei(GL_UNPACK_IMAGE_HEIGHT,	m_imageHeight);
2498		glPixelStorei(GL_UNPACK_ROW_LENGTH,		m_rowLength);
2499		glPixelStorei(GL_UNPACK_SKIP_IMAGES,	m_skipImages);
2500		glPixelStorei(GL_UNPACK_SKIP_ROWS,		m_skipRows);
2501		glPixelStorei(GL_UNPACK_SKIP_PIXELS,	m_skipPixels);
2502		glPixelStorei(GL_UNPACK_ALIGNMENT,		m_alignment);
2503
2504		glGenTextures(1, &tex);
2505		glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
2506		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, m_internalFormat, m_width, m_height, m_numLayers, 0, transferFmt.format, transferFmt.dataType, (const void*)(deUintptr)m_offset);
2507	}
2508
2509	deUint32	m_internalFormat;
2510	int			m_imageHeight;
2511	int			m_rowLength;
2512	int			m_skipImages;
2513	int			m_skipRows;
2514	int			m_skipPixels;
2515	int			m_alignment;
2516	int			m_offset;
2517};
2518
2519// TexImage3D() from pixel buffer object.
2520class TexImage3DBufferCase : public Texture3DSpecCase
2521{
2522public:
2523	TexImage3DBufferCase (Context&		context,
2524						  const char*	name,
2525						  const char*	desc,
2526						  deUint32		internalFormat,
2527						  int			width,
2528						  int			height,
2529						  int			depth,
2530						  int			imageHeight,
2531						  int			rowLength,
2532						  int			skipImages,
2533						  int			skipRows,
2534						  int			skipPixels,
2535						  int			alignment,
2536						  int			offset)
2537		: Texture3DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth, 1)
2538		, m_internalFormat	(internalFormat)
2539		, m_imageHeight		(imageHeight)
2540		, m_rowLength		(rowLength)
2541		, m_skipImages		(skipImages)
2542		, m_skipRows		(skipRows)
2543		, m_skipPixels		(skipPixels)
2544		, m_alignment		(alignment)
2545		, m_offset			(offset)
2546	{
2547	}
2548
2549protected:
2550	void createTexture (void)
2551	{
2552		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
2553		int						pixelSize		= m_texFormat.getPixelSize();
2554		int						rowLength		= m_rowLength > 0 ? m_rowLength : m_width;
2555		int						rowPitch		= deAlign32(rowLength*pixelSize, m_alignment);
2556		int						imageHeight		= m_imageHeight > 0 ? m_imageHeight : m_height;
2557		int						slicePitch		= imageHeight*rowPitch;
2558		deUint32				tex				= 0;
2559		deUint32				buf				= 0;
2560		vector<deUint8>			data;
2561
2562		DE_ASSERT(m_numLevels == 1);
2563
2564		// Fill data with grid.
2565		data.resize(slicePitch*(m_depth+m_skipImages) + m_offset);
2566		{
2567			Vec4	cScale		= m_texFormatInfo.valueMax-m_texFormatInfo.valueMin;
2568			Vec4	cBias		= m_texFormatInfo.valueMin;
2569			Vec4	colorA		= Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
2570			Vec4	colorB		= Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias;
2571
2572			tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, m_depth, rowPitch, slicePitch, &data[0] + m_skipImages*slicePitch + m_skipRows*rowPitch + m_skipPixels*pixelSize + m_offset), 4, colorA, colorB);
2573		}
2574
2575		glGenBuffers(1, &buf);
2576		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
2577		glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
2578
2579		glPixelStorei(GL_UNPACK_IMAGE_HEIGHT,	m_imageHeight);
2580		glPixelStorei(GL_UNPACK_ROW_LENGTH,		m_rowLength);
2581		glPixelStorei(GL_UNPACK_SKIP_IMAGES,	m_skipImages);
2582		glPixelStorei(GL_UNPACK_SKIP_ROWS,		m_skipRows);
2583		glPixelStorei(GL_UNPACK_SKIP_PIXELS,	m_skipPixels);
2584		glPixelStorei(GL_UNPACK_ALIGNMENT,		m_alignment);
2585
2586		glGenTextures(1, &tex);
2587		glBindTexture(GL_TEXTURE_3D, tex);
2588		glTexImage3D(GL_TEXTURE_3D, 0, m_internalFormat, m_width, m_height, m_depth, 0, transferFmt.format, transferFmt.dataType, (const void*)(deUintptr)m_offset);
2589	}
2590
2591	deUint32	m_internalFormat;
2592	int			m_imageHeight;
2593	int			m_rowLength;
2594	int			m_skipImages;
2595	int			m_skipRows;
2596	int			m_skipPixels;
2597	int			m_alignment;
2598	int			m_offset;
2599};
2600
2601// TexSubImage2D() PBO case.
2602class TexSubImage2DBufferCase : public Texture2DSpecCase
2603{
2604public:
2605	TexSubImage2DBufferCase (Context&		context,
2606							 const char*	name,
2607							 const char*	desc,
2608							 deUint32		internalFormat,
2609							 int			width,
2610							 int			height,
2611							 int			subX,
2612							 int			subY,
2613							 int			subW,
2614							 int			subH,
2615							 int			rowLength,
2616							 int			skipRows,
2617							 int			skipPixels,
2618							 int			alignment,
2619							 int			offset)
2620		: Texture2DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, 1)
2621		, m_internalFormat	(internalFormat)
2622		, m_subX			(subX)
2623		, m_subY			(subY)
2624		, m_subW			(subW)
2625		, m_subH			(subH)
2626		, m_rowLength		(rowLength)
2627		, m_skipRows		(skipRows)
2628		, m_skipPixels		(skipPixels)
2629		, m_alignment		(alignment)
2630		, m_offset			(offset)
2631	{
2632	}
2633
2634protected:
2635	void createTexture (void)
2636	{
2637		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
2638		int						pixelSize		= m_texFormat.getPixelSize();
2639		deUint32				tex				= 0;
2640		deUint32				buf				= 0;
2641		vector<deUint8>			data;
2642
2643		DE_ASSERT(m_numLevels == 1);
2644
2645		glGenTextures(1, &tex);
2646		glBindTexture(GL_TEXTURE_2D, tex);
2647
2648		// First fill texture with gradient.
2649		data.resize(deAlign32(m_width*pixelSize, 4)*m_height);
2650		tcu::fillWithComponentGradients(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, 1, deAlign32(m_width*pixelSize, 4), 0, &data[0]), m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2651		glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, transferFmt.format, transferFmt.dataType, &data[0]);
2652
2653		// Fill data with grid.
2654		{
2655			int		rowLength	= m_rowLength > 0 ? m_rowLength : m_subW;
2656			int		rowPitch	= deAlign32(rowLength*pixelSize, m_alignment);
2657			int		height		= m_subH + m_skipRows;
2658			Vec4	cScale		= m_texFormatInfo.valueMax-m_texFormatInfo.valueMin;
2659			Vec4	cBias		= m_texFormatInfo.valueMin;
2660			Vec4	colorA		= Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
2661			Vec4	colorB		= Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias;
2662
2663			data.resize(rowPitch*height + m_offset);
2664			tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_subW, m_subH, 1, rowPitch, 0, &data[0] + m_skipRows*rowPitch + m_skipPixels*pixelSize + m_offset), 4, colorA, colorB);
2665		}
2666
2667		glGenBuffers(1, &buf);
2668		glBindBuffer(GL_PIXEL_UNPACK_BUFFER,	buf);
2669		glBufferData(GL_PIXEL_UNPACK_BUFFER,	(int)data.size(), &data[0], GL_STATIC_DRAW);
2670
2671		glPixelStorei(GL_UNPACK_ROW_LENGTH,		m_rowLength);
2672		glPixelStorei(GL_UNPACK_SKIP_ROWS,		m_skipRows);
2673		glPixelStorei(GL_UNPACK_SKIP_PIXELS,	m_skipPixels);
2674		glPixelStorei(GL_UNPACK_ALIGNMENT,		m_alignment);
2675		glTexSubImage2D(GL_TEXTURE_2D, 0, m_subX, m_subY, m_subW, m_subH, transferFmt.format, transferFmt.dataType, (const void*)(deUintptr)m_offset);
2676	}
2677
2678	deUint32	m_internalFormat;
2679	int			m_subX;
2680	int			m_subY;
2681	int			m_subW;
2682	int			m_subH;
2683	int			m_rowLength;
2684	int			m_skipRows;
2685	int			m_skipPixels;
2686	int			m_alignment;
2687	int			m_offset;
2688};
2689
2690// TexSubImage2D() cubemap PBO case.
2691class TexSubImageCubeBufferCase : public TextureCubeSpecCase
2692{
2693public:
2694	TexSubImageCubeBufferCase	(Context&		context,
2695								 const char*	name,
2696								 const char*	desc,
2697								 deUint32		internalFormat,
2698								 int			size,
2699								 int			subX,
2700								 int			subY,
2701								 int			subW,
2702								 int			subH,
2703								 int			rowLength,
2704								 int			skipRows,
2705								 int			skipPixels,
2706								 int			alignment,
2707								 int			offset)
2708		: TextureCubeSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), size, 1)
2709		, m_internalFormat		(internalFormat)
2710		, m_subX				(subX)
2711		, m_subY				(subY)
2712		, m_subW				(subW)
2713		, m_subH				(subH)
2714		, m_rowLength			(rowLength)
2715		, m_skipRows			(skipRows)
2716		, m_skipPixels			(skipPixels)
2717		, m_alignment			(alignment)
2718		, m_offset				(offset)
2719	{
2720	}
2721
2722protected:
2723	void createTexture (void)
2724	{
2725		de::Random				rnd				(deStringHash(getName()));
2726		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
2727		int						pixelSize		= m_texFormat.getPixelSize();
2728		deUint32				tex				= 0;
2729		deUint32				buf				= 0;
2730		vector<deUint8>			data;
2731
2732		DE_ASSERT(m_numLevels == 1);
2733
2734		glGenTextures(1, &tex);
2735		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
2736
2737		// Fill faces with different gradients.
2738
2739		data.resize(deAlign32(m_size*pixelSize, 4)*m_size);
2740		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2741
2742		for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
2743		{
2744			const Vec4 gMin = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2745			const Vec4 gMax = randomVector<4>(rnd, m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2746
2747			tcu::fillWithComponentGradients(tcu::PixelBufferAccess(m_texFormat, m_size, m_size, 1, deAlign32(m_size*pixelSize, 4), 0, &data[0]), gMin, gMax);
2748
2749			glTexImage2D(s_cubeMapFaces[face], 0, m_internalFormat, m_size, m_size, 0, transferFmt.format, transferFmt.dataType, &data[0]);
2750		}
2751
2752		// Fill data with grid.
2753		{
2754			int		rowLength	= m_rowLength > 0 ? m_rowLength : m_subW;
2755			int		rowPitch	= deAlign32(rowLength*pixelSize, m_alignment);
2756			int		height		= m_subH + m_skipRows;
2757			Vec4	cScale		= m_texFormatInfo.valueMax-m_texFormatInfo.valueMin;
2758			Vec4	cBias		= m_texFormatInfo.valueMin;
2759			Vec4	colorA		= Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
2760			Vec4	colorB		= Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias;
2761
2762			data.resize(rowPitch*height + m_offset);
2763			tcu::fillWithGrid(tcu::PixelBufferAccess(m_texFormat, m_subW, m_subH, 1, rowPitch, 0, &data[0] + m_skipRows*rowPitch + m_skipPixels*pixelSize + m_offset), 4, colorA, colorB);
2764		}
2765
2766		glGenBuffers(1, &buf);
2767		glBindBuffer(GL_PIXEL_UNPACK_BUFFER,	buf);
2768		glBufferData(GL_PIXEL_UNPACK_BUFFER,	(int)data.size(), &data[0], GL_STATIC_DRAW);
2769
2770		glPixelStorei(GL_UNPACK_ROW_LENGTH,		m_rowLength);
2771		glPixelStorei(GL_UNPACK_SKIP_ROWS,		m_skipRows);
2772		glPixelStorei(GL_UNPACK_SKIP_PIXELS,	m_skipPixels);
2773		glPixelStorei(GL_UNPACK_ALIGNMENT,		m_alignment);
2774
2775		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
2776			glTexSubImage2D(s_cubeMapFaces[face], 0, m_subX, m_subY, m_subW, m_subH, transferFmt.format, transferFmt.dataType, (const void*)(deUintptr)m_offset);
2777	}
2778
2779	deUint32	m_internalFormat;
2780	int			m_subX;
2781	int			m_subY;
2782	int			m_subW;
2783	int			m_subH;
2784	int			m_rowLength;
2785	int			m_skipRows;
2786	int			m_skipPixels;
2787	int			m_alignment;
2788	int			m_offset;
2789};
2790
2791// TexSubImage3D() 2D array PBO case.
2792class TexSubImage2DArrayBufferCase : public Texture2DArraySpecCase
2793{
2794public:
2795	TexSubImage2DArrayBufferCase (Context&		context,
2796								 const char*	name,
2797								 const char*	desc,
2798								 deUint32		internalFormat,
2799								 int			width,
2800								 int			height,
2801								 int			depth,
2802								 int			subX,
2803								 int			subY,
2804								 int			subZ,
2805								 int			subW,
2806								 int			subH,
2807								 int			subD,
2808								 int			imageHeight,
2809								 int			rowLength,
2810								 int			skipImages,
2811								 int			skipRows,
2812								 int			skipPixels,
2813								 int			alignment,
2814								 int			offset)
2815		: Texture2DArraySpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth, 1)
2816		, m_internalFormat			(internalFormat)
2817		, m_subX					(subX)
2818		, m_subY					(subY)
2819		, m_subZ					(subZ)
2820		, m_subW					(subW)
2821		, m_subH					(subH)
2822		, m_subD					(subD)
2823		, m_imageHeight				(imageHeight)
2824		, m_rowLength				(rowLength)
2825		, m_skipImages				(skipImages)
2826		, m_skipRows				(skipRows)
2827		, m_skipPixels				(skipPixels)
2828		, m_alignment				(alignment)
2829		, m_offset					(offset)
2830	{
2831	}
2832
2833protected:
2834	void createTexture (void)
2835	{
2836		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
2837		int						pixelSize		= m_texFormat.getPixelSize();
2838		deUint32				tex				= 0;
2839		deUint32				buf				= 0;
2840		vector<deUint8>			data;
2841
2842		DE_ASSERT(m_numLevels == 1);
2843
2844		glGenTextures(1, &tex);
2845		glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
2846
2847		// Fill with gradient.
2848		{
2849			int		rowPitch		= deAlign32(pixelSize*m_width,  4);
2850			int		slicePitch		= rowPitch*m_height;
2851
2852			data.resize(slicePitch*m_numLayers);
2853			tcu::fillWithComponentGradients(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, m_numLayers, rowPitch, slicePitch, &data[0]), m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2854		}
2855
2856		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, m_internalFormat, m_width, m_height, m_numLayers, 0, transferFmt.format, transferFmt.dataType, &data[0]);
2857
2858		// Fill data with grid.
2859		{
2860			int		rowLength		= m_rowLength > 0 ? m_rowLength : m_subW;
2861			int		rowPitch		= deAlign32(rowLength*pixelSize, m_alignment);
2862			int		imageHeight		= m_imageHeight > 0 ? m_imageHeight : m_subH;
2863			int		slicePitch		= imageHeight*rowPitch;
2864			Vec4	cScale			= m_texFormatInfo.valueMax-m_texFormatInfo.valueMin;
2865			Vec4	cBias			= m_texFormatInfo.valueMin;
2866			Vec4	colorA			= Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
2867			Vec4	colorB			= Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias;
2868
2869			data.resize(slicePitch*(m_numLayers+m_skipImages) + m_offset);
2870			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);
2871		}
2872
2873		glGenBuffers(1, &buf);
2874		glBindBuffer(GL_PIXEL_UNPACK_BUFFER,	buf);
2875		glBufferData(GL_PIXEL_UNPACK_BUFFER,	(int)data.size(), &data[0], GL_STATIC_DRAW);
2876
2877		glPixelStorei(GL_UNPACK_IMAGE_HEIGHT,	m_imageHeight);
2878		glPixelStorei(GL_UNPACK_ROW_LENGTH,		m_rowLength);
2879		glPixelStorei(GL_UNPACK_SKIP_IMAGES,	m_skipImages);
2880		glPixelStorei(GL_UNPACK_SKIP_ROWS,		m_skipRows);
2881		glPixelStorei(GL_UNPACK_SKIP_PIXELS,	m_skipPixels);
2882		glPixelStorei(GL_UNPACK_ALIGNMENT,		m_alignment);
2883		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, m_subX, m_subY, m_subZ, m_subW, m_subH, m_subD, transferFmt.format, transferFmt.dataType, (const void*)(deIntptr)m_offset);
2884	}
2885
2886	deUint32	m_internalFormat;
2887	int			m_subX;
2888	int			m_subY;
2889	int			m_subZ;
2890	int			m_subW;
2891	int			m_subH;
2892	int			m_subD;
2893	int			m_imageHeight;
2894	int			m_rowLength;
2895	int			m_skipImages;
2896	int			m_skipRows;
2897	int			m_skipPixels;
2898	int			m_alignment;
2899	int			m_offset;
2900};
2901
2902// TexSubImage3D() PBO case.
2903class TexSubImage3DBufferCase : public Texture3DSpecCase
2904{
2905public:
2906	TexSubImage3DBufferCase (Context&		context,
2907							 const char*	name,
2908							 const char*	desc,
2909							 deUint32		internalFormat,
2910							 int			width,
2911							 int			height,
2912							 int			depth,
2913							 int			subX,
2914							 int			subY,
2915							 int			subZ,
2916							 int			subW,
2917							 int			subH,
2918							 int			subD,
2919							 int			imageHeight,
2920							 int			rowLength,
2921							 int			skipImages,
2922							 int			skipRows,
2923							 int			skipPixels,
2924							 int			alignment,
2925							 int			offset)
2926		: Texture3DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), width, height, depth, 1)
2927		, m_internalFormat	(internalFormat)
2928		, m_subX			(subX)
2929		, m_subY			(subY)
2930		, m_subZ			(subZ)
2931		, m_subW			(subW)
2932		, m_subH			(subH)
2933		, m_subD			(subD)
2934		, m_imageHeight		(imageHeight)
2935		, m_rowLength		(rowLength)
2936		, m_skipImages		(skipImages)
2937		, m_skipRows		(skipRows)
2938		, m_skipPixels		(skipPixels)
2939		, m_alignment		(alignment)
2940		, m_offset			(offset)
2941	{
2942	}
2943
2944protected:
2945	void createTexture (void)
2946	{
2947		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
2948		int						pixelSize		= m_texFormat.getPixelSize();
2949		deUint32				tex				= 0;
2950		deUint32				buf				= 0;
2951		vector<deUint8>			data;
2952
2953		DE_ASSERT(m_numLevels == 1);
2954
2955		glGenTextures(1, &tex);
2956		glBindTexture(GL_TEXTURE_3D, tex);
2957
2958		// Fill with gradient.
2959		{
2960			int		rowPitch		= deAlign32(pixelSize*m_width,  4);
2961			int		slicePitch		= rowPitch*m_height;
2962
2963			data.resize(slicePitch*m_depth);
2964			tcu::fillWithComponentGradients(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, m_depth, rowPitch, slicePitch, &data[0]), m_texFormatInfo.valueMin, m_texFormatInfo.valueMax);
2965		}
2966
2967		glTexImage3D(GL_TEXTURE_3D, 0, m_internalFormat, m_width, m_height, m_depth, 0, transferFmt.format, transferFmt.dataType, &data[0]);
2968
2969		// Fill data with grid.
2970		{
2971			int		rowLength		= m_rowLength > 0 ? m_rowLength : m_subW;
2972			int		rowPitch		= deAlign32(rowLength*pixelSize, m_alignment);
2973			int		imageHeight		= m_imageHeight > 0 ? m_imageHeight : m_subH;
2974			int		slicePitch		= imageHeight*rowPitch;
2975			Vec4	cScale			= m_texFormatInfo.valueMax-m_texFormatInfo.valueMin;
2976			Vec4	cBias			= m_texFormatInfo.valueMin;
2977			Vec4	colorA			= Vec4(1.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
2978			Vec4	colorB			= Vec4(0.0f, 1.0f, 0.0f, 1.0f)*cScale + cBias;
2979
2980			data.resize(slicePitch*(m_depth+m_skipImages) + m_offset);
2981			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);
2982		}
2983
2984		glGenBuffers(1, &buf);
2985		glBindBuffer(GL_PIXEL_UNPACK_BUFFER,	buf);
2986		glBufferData(GL_PIXEL_UNPACK_BUFFER,	(int)data.size(), &data[0], GL_STATIC_DRAW);
2987
2988		glPixelStorei(GL_UNPACK_IMAGE_HEIGHT,	m_imageHeight);
2989		glPixelStorei(GL_UNPACK_ROW_LENGTH,		m_rowLength);
2990		glPixelStorei(GL_UNPACK_SKIP_IMAGES,	m_skipImages);
2991		glPixelStorei(GL_UNPACK_SKIP_ROWS,		m_skipRows);
2992		glPixelStorei(GL_UNPACK_SKIP_PIXELS,	m_skipPixels);
2993		glPixelStorei(GL_UNPACK_ALIGNMENT,		m_alignment);
2994		glTexSubImage3D(GL_TEXTURE_3D, 0, m_subX, m_subY, m_subZ, m_subW, m_subH, m_subD, transferFmt.format, transferFmt.dataType, (const void*)(deIntptr)m_offset);
2995	}
2996
2997	deUint32	m_internalFormat;
2998	int			m_subX;
2999	int			m_subY;
3000	int			m_subZ;
3001	int			m_subW;
3002	int			m_subH;
3003	int			m_subD;
3004	int			m_imageHeight;
3005	int			m_rowLength;
3006	int			m_skipImages;
3007	int			m_skipRows;
3008	int			m_skipPixels;
3009	int			m_alignment;
3010	int			m_offset;
3011};
3012
3013// TexImage2D() depth case.
3014class TexImage2DDepthCase : public Texture2DSpecCase
3015{
3016public:
3017	TexImage2DDepthCase (Context&		context,
3018						 const char*	name,
3019						 const char*	desc,
3020						 deUint32		internalFormat,
3021						 int			imageWidth,
3022						 int			imageHeight)
3023		: Texture2DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageWidth, imageHeight, maxLevelCount(imageWidth, imageHeight))
3024		, m_internalFormat	(internalFormat)
3025	{
3026		// we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
3027		m_texFormatInfo.lookupBias = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
3028		m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
3029	}
3030
3031	void createTexture (void)
3032	{
3033		glu::TransferFormat	fmt			= glu::getTransferFormat(m_texFormat);
3034		deUint32			tex			= 0;
3035		tcu::TextureLevel	levelData	(m_texFormat);
3036
3037		glGenTextures(1, &tex);
3038		glBindTexture(GL_TEXTURE_2D, tex);
3039		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
3040		GLU_CHECK();
3041
3042		for (int ndx = 0; ndx < m_numLevels; ndx++)
3043		{
3044			const int   levelW		= de::max(1, m_width >> ndx);
3045			const int   levelH		= de::max(1, m_height >> ndx);
3046			const Vec4  gMin		= Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
3047			const Vec4  gMax		= Vec4(2.0f, 1.5f, -1.0f, 2.0f);
3048
3049			levelData.setSize(levelW, levelH);
3050			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
3051
3052			glTexImage2D(GL_TEXTURE_2D, ndx, m_internalFormat, levelW, levelH, 0, fmt.format, fmt.dataType, levelData.getAccess().getDataPtr());
3053		}
3054	}
3055
3056	const deUint32 m_internalFormat;
3057};
3058
3059// TexImage3D() depth case.
3060class TexImage2DArrayDepthCase : public Texture2DArraySpecCase
3061{
3062public:
3063	TexImage2DArrayDepthCase (Context&		context,
3064							  const char*	name,
3065							  const char*	desc,
3066							  deUint32		internalFormat,
3067							  int			imageWidth,
3068							  int			imageHeight,
3069							  int			numLayers)
3070		: Texture2DArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageWidth, imageHeight, numLayers, maxLevelCount(imageWidth, imageHeight))
3071		, m_internalFormat		(internalFormat)
3072	{
3073		// we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
3074		m_texFormatInfo.lookupBias = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
3075		m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
3076	}
3077
3078	void createTexture (void)
3079	{
3080		glu::TransferFormat	fmt			= glu::getTransferFormat(m_texFormat);
3081		deUint32			tex			= 0;
3082		tcu::TextureLevel	levelData	(m_texFormat);
3083
3084		glGenTextures(1, &tex);
3085		glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
3086		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
3087		GLU_CHECK();
3088
3089		for (int ndx = 0; ndx < m_numLevels; ndx++)
3090		{
3091			const int   levelW		= de::max(1, m_width >> ndx);
3092			const int   levelH		= de::max(1, m_height >> ndx);
3093			const Vec4  gMin		= Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
3094			const Vec4  gMax		= Vec4(2.0f, 1.5f, -1.0f, 2.0f);
3095
3096			levelData.setSize(levelW, levelH, m_numLayers);
3097			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
3098
3099			glTexImage3D(GL_TEXTURE_2D_ARRAY, ndx, m_internalFormat, levelW, levelH, m_numLayers, 0, fmt.format, fmt.dataType, levelData.getAccess().getDataPtr());
3100		}
3101	}
3102
3103	const deUint32 m_internalFormat;
3104};
3105
3106// TexSubImage2D() depth case.
3107class TexSubImage2DDepthCase : public Texture2DSpecCase
3108{
3109public:
3110	TexSubImage2DDepthCase (Context&	context,
3111							const char*	name,
3112							const char*	desc,
3113							deUint32	internalFormat,
3114							int			imageWidth,
3115							int			imageHeight)
3116		: Texture2DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageWidth, imageHeight, maxLevelCount(imageWidth, imageHeight))
3117		, m_internalFormat	(internalFormat)
3118	{
3119		// we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
3120		m_texFormatInfo.lookupBias = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
3121		m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
3122	}
3123
3124	void createTexture (void)
3125	{
3126		glu::TransferFormat	fmt			= glu::getTransferFormat(m_texFormat);
3127		de::Random			rnd			(deStringHash(getName()));
3128		deUint32			tex			= 0;
3129		tcu::TextureLevel	levelData	(m_texFormat);
3130
3131		glGenTextures(1, &tex);
3132		glBindTexture(GL_TEXTURE_2D, tex);
3133		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
3134		GLU_CHECK();
3135
3136		// First specify full texture.
3137		for (int ndx = 0; ndx < m_numLevels; ndx++)
3138		{
3139			const int   levelW		= de::max(1, m_width >> ndx);
3140			const int   levelH		= de::max(1, m_height >> ndx);
3141			const Vec4  gMin		= Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
3142			const Vec4  gMax		= Vec4(2.0f, 1.5f, -1.0f, 2.0f);
3143
3144			levelData.setSize(levelW, levelH);
3145			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
3146
3147			glTexImage2D(GL_TEXTURE_2D, ndx, m_internalFormat, levelW, levelH, 0, fmt.format, fmt.dataType, levelData.getAccess().getDataPtr());
3148		}
3149
3150		// Re-specify parts of each level.
3151		for (int ndx = 0; ndx < m_numLevels; ndx++)
3152		{
3153			const int	levelW		= de::max(1, m_width >> ndx);
3154			const int	levelH		= de::max(1, m_height >> ndx);
3155
3156			const int	w			= rnd.getInt(1, levelW);
3157			const int	h			= rnd.getInt(1, levelH);
3158			const int	x			= rnd.getInt(0, levelW-w);
3159			const int	y			= rnd.getInt(0, levelH-h);
3160
3161			const Vec4	colorA		= Vec4(2.0f, 1.5f, -1.0f, 2.0f);
3162			const Vec4	colorB		= Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
3163			const int	cellSize	= rnd.getInt(2, 16);
3164
3165			levelData.setSize(w, h);
3166			tcu::fillWithGrid(levelData.getAccess(), cellSize, colorA, colorB);
3167
3168			glTexSubImage2D(GL_TEXTURE_2D, ndx, x, y, w, h, fmt.format, fmt.dataType, levelData.getAccess().getDataPtr());
3169		}
3170	}
3171
3172	const deUint32 m_internalFormat;
3173};
3174
3175// TexSubImage3D() depth case.
3176class TexSubImage2DArrayDepthCase : public Texture2DArraySpecCase
3177{
3178public:
3179	TexSubImage2DArrayDepthCase (Context&		context,
3180								 const char*	name,
3181								 const char*	desc,
3182								 deUint32		internalFormat,
3183								 int			imageWidth,
3184								 int			imageHeight,
3185								 int			numLayers)
3186		: Texture2DArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageWidth, imageHeight, numLayers, maxLevelCount(imageWidth, imageHeight))
3187		, m_internalFormat		(internalFormat)
3188	{
3189		// we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
3190		m_texFormatInfo.lookupBias = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
3191		m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
3192	}
3193
3194	void createTexture (void)
3195	{
3196		glu::TransferFormat	fmt			= glu::getTransferFormat(m_texFormat);
3197		de::Random			rnd			(deStringHash(getName()));
3198		deUint32			tex			= 0;
3199		tcu::TextureLevel	levelData	(m_texFormat);
3200
3201		glGenTextures(1, &tex);
3202		glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
3203		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
3204		GLU_CHECK();
3205
3206		// First specify full texture.
3207		for (int ndx = 0; ndx < m_numLevels; ndx++)
3208		{
3209			const int   levelW		= de::max(1, m_width >> ndx);
3210			const int   levelH		= de::max(1, m_height >> ndx);
3211			const Vec4  gMin		= Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
3212			const Vec4  gMax		= Vec4(2.0f, 1.5f, -1.0f, 2.0f);
3213
3214			levelData.setSize(levelW, levelH, m_numLayers);
3215			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
3216
3217			glTexImage3D(GL_TEXTURE_2D_ARRAY, ndx, m_internalFormat, levelW, levelH, m_numLayers, 0, fmt.format, fmt.dataType, levelData.getAccess().getDataPtr());
3218		}
3219
3220		// Re-specify parts of each level.
3221		for (int ndx = 0; ndx < m_numLevels; ndx++)
3222		{
3223			const int	levelW		= de::max(1, m_width >> ndx);
3224			const int	levelH		= de::max(1, m_height >> ndx);
3225
3226			const int	w			= rnd.getInt(1, levelW);
3227			const int	h			= rnd.getInt(1, levelH);
3228			const int	d			= rnd.getInt(1, m_numLayers);
3229			const int	x			= rnd.getInt(0, levelW-w);
3230			const int	y			= rnd.getInt(0, levelH-h);
3231			const int	z			= rnd.getInt(0, m_numLayers-d);
3232
3233			const Vec4	colorA		= Vec4(2.0f, 1.5f, -1.0f, 2.0f);
3234			const Vec4	colorB		= Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
3235			const int	cellSize	= rnd.getInt(2, 16);
3236
3237			levelData.setSize(w, h, d);
3238			tcu::fillWithGrid(levelData.getAccess(), cellSize, colorA, colorB);
3239
3240			glTexSubImage3D(GL_TEXTURE_2D_ARRAY, ndx, x, y, z, w, h, d, fmt.format, fmt.dataType, levelData.getAccess().getDataPtr());
3241		}
3242	}
3243
3244	const deUint32 m_internalFormat;
3245};
3246
3247// TexImage2D() depth case with pbo.
3248class TexImage2DDepthBufferCase : public Texture2DSpecCase
3249{
3250public:
3251	TexImage2DDepthBufferCase (Context&		context,
3252							   const char*	name,
3253							   const char*	desc,
3254							   deUint32		internalFormat,
3255							   int			imageWidth,
3256							   int			imageHeight)
3257		: Texture2DSpecCase	(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageWidth, imageHeight, 1)
3258		, m_internalFormat	(internalFormat)
3259	{
3260		// we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
3261		m_texFormatInfo.lookupBias = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
3262		m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
3263	}
3264
3265	void createTexture (void)
3266	{
3267		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
3268		int						pixelSize		= m_texFormat.getPixelSize();
3269		int						rowLength		= m_width;
3270		int						alignment		= 4;
3271		int						rowPitch		= deAlign32(rowLength*pixelSize, alignment);
3272		int						height			= m_height;
3273		deUint32				buf				= 0;
3274		deUint32				tex				= 0;
3275		vector<deUint8>			data;
3276
3277		DE_ASSERT(m_numLevels == 1);
3278
3279		// Fill data with gradient
3280		data.resize(rowPitch*height);
3281		{
3282			const Vec4 gMin = Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
3283			const Vec4 gMax = Vec4(2.0f, 1.5f, -1.0f, 2.0f);
3284
3285			tcu::fillWithComponentGradients(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, 1, rowPitch, 0, &data[0]), gMin, gMax);
3286		}
3287
3288		// Create buffer and upload.
3289		glGenBuffers(1, &buf);
3290		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
3291		glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
3292
3293		glPixelStorei(GL_UNPACK_ROW_LENGTH,		rowLength);
3294		glPixelStorei(GL_UNPACK_SKIP_ROWS,		0);
3295		glPixelStorei(GL_UNPACK_SKIP_PIXELS,	0);
3296		glPixelStorei(GL_UNPACK_ALIGNMENT,		alignment);
3297
3298		glGenTextures(1, &tex);
3299		glBindTexture(GL_TEXTURE_2D, tex);
3300		glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_width, m_height, 0, transferFmt.format, transferFmt.dataType, DE_NULL);
3301		glDeleteBuffers(1, &buf);
3302	}
3303
3304	const deUint32 m_internalFormat;
3305};
3306
3307// TexImage3D() depth case with pbo.
3308class TexImage2DArrayDepthBufferCase : public Texture2DArraySpecCase
3309{
3310public:
3311	TexImage2DArrayDepthBufferCase (Context&	context,
3312									const char*	name,
3313									const char*	desc,
3314									deUint32	internalFormat,
3315									int			imageWidth,
3316									int			imageHeight,
3317									int			numLayers)
3318		: Texture2DArraySpecCase(context, name, desc, glu::mapGLInternalFormat(internalFormat), imageWidth, imageHeight, numLayers, 1)
3319		, m_internalFormat		(internalFormat)
3320	{
3321		// we are interested in the behavior near [-2, 2], map it to visible range [0, 1]
3322		m_texFormatInfo.lookupBias = Vec4(0.25f, 0.0f, 0.0f, 1.0f);
3323		m_texFormatInfo.lookupScale = Vec4(0.5f, 1.0f, 1.0f, 0.0f);
3324	}
3325
3326	void createTexture (void)
3327	{
3328		glu::TransferFormat		transferFmt		= glu::getTransferFormat(m_texFormat);
3329		int						pixelSize		= m_texFormat.getPixelSize();
3330		int						rowLength		= m_width;
3331		int						alignment		= 4;
3332		int						rowPitch		= deAlign32(rowLength*pixelSize, alignment);
3333		int						imageHeight		= m_height;
3334		int						slicePitch		= imageHeight*rowPitch;
3335		deUint32				tex				= 0;
3336		deUint32				buf				= 0;
3337		vector<deUint8>			data;
3338
3339		DE_ASSERT(m_numLevels == 1);
3340
3341		// Fill data with grid.
3342		data.resize(slicePitch*m_numLayers);
3343		{
3344			const Vec4 gMin = Vec4(-1.5f, -2.0f, 1.7f, -1.5f);
3345			const Vec4 gMax = Vec4(2.0f, 1.5f, -1.0f, 2.0f);
3346
3347			tcu::fillWithComponentGradients(tcu::PixelBufferAccess(m_texFormat, m_width, m_height, m_numLayers, rowPitch, slicePitch, &data[0]), gMin, gMax);
3348		}
3349
3350		glGenBuffers(1, &buf);
3351		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf);
3352		glBufferData(GL_PIXEL_UNPACK_BUFFER, (int)data.size(), &data[0], GL_STATIC_DRAW);
3353
3354		glPixelStorei(GL_UNPACK_IMAGE_HEIGHT,	imageHeight);
3355		glPixelStorei(GL_UNPACK_ROW_LENGTH,		rowLength);
3356		glPixelStorei(GL_UNPACK_SKIP_IMAGES,	0);
3357		glPixelStorei(GL_UNPACK_SKIP_ROWS,		0);
3358		glPixelStorei(GL_UNPACK_SKIP_PIXELS,	0);
3359		glPixelStorei(GL_UNPACK_ALIGNMENT,		alignment);
3360
3361		glGenTextures(1, &tex);
3362		glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
3363		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, m_internalFormat, m_width, m_height, m_numLayers, 0, transferFmt.format, transferFmt.dataType, DE_NULL);
3364		glDeleteBuffers(1, &buf);
3365	}
3366
3367	const deUint32 m_internalFormat;
3368};
3369
3370TextureSpecificationTests::TextureSpecificationTests (Context& context)
3371	: TestCaseGroup(context, "specification", "Texture Specification Tests")
3372{
3373}
3374
3375TextureSpecificationTests::~TextureSpecificationTests (void)
3376{
3377}
3378
3379void TextureSpecificationTests::init (void)
3380{
3381	struct
3382	{
3383		const char*	name;
3384		deUint32	format;
3385		deUint32	dataType;
3386	} unsizedFormats[] =
3387	{
3388		{ "alpha_unsigned_byte",			GL_ALPHA,			GL_UNSIGNED_BYTE },
3389		{ "luminance_unsigned_byte",		GL_LUMINANCE,		GL_UNSIGNED_BYTE },
3390		{ "luminance_alpha_unsigned_byte",	GL_LUMINANCE_ALPHA,	GL_UNSIGNED_BYTE },
3391		{ "rgb_unsigned_short_5_6_5",		GL_RGB,				GL_UNSIGNED_SHORT_5_6_5 },
3392		{ "rgb_unsigned_byte",				GL_RGB,				GL_UNSIGNED_BYTE },
3393		{ "rgba_unsigned_short_4_4_4_4",	GL_RGBA,			GL_UNSIGNED_SHORT_4_4_4_4 },
3394		{ "rgba_unsigned_short_5_5_5_1",	GL_RGBA,			GL_UNSIGNED_SHORT_5_5_5_1 },
3395		{ "rgba_unsigned_byte",				GL_RGBA,			GL_UNSIGNED_BYTE }
3396	};
3397
3398	struct
3399	{
3400		const char*	name;
3401		deUint32	internalFormat;
3402	} colorFormats[] =
3403	{
3404		{ "rgba32f",			GL_RGBA32F,			},
3405		{ "rgba32i",			GL_RGBA32I,			},
3406		{ "rgba32ui",			GL_RGBA32UI,		},
3407		{ "rgba16f",			GL_RGBA16F,			},
3408		{ "rgba16i",			GL_RGBA16I,			},
3409		{ "rgba16ui",			GL_RGBA16UI,		},
3410		{ "rgba8",				GL_RGBA8,			},
3411		{ "rgba8i",				GL_RGBA8I,			},
3412		{ "rgba8ui",			GL_RGBA8UI,			},
3413		{ "srgb8_alpha8",		GL_SRGB8_ALPHA8,	},
3414		{ "rgb10_a2",			GL_RGB10_A2,		},
3415		{ "rgb10_a2ui",			GL_RGB10_A2UI,		},
3416		{ "rgba4",				GL_RGBA4,			},
3417		{ "rgb5_a1",			GL_RGB5_A1,			},
3418		{ "rgba8_snorm",		GL_RGBA8_SNORM,		},
3419		{ "rgb8",				GL_RGB8,			},
3420		{ "rgb565",				GL_RGB565,			},
3421		{ "r11f_g11f_b10f",		GL_R11F_G11F_B10F,	},
3422		{ "rgb32f",				GL_RGB32F,			},
3423		{ "rgb32i",				GL_RGB32I,			},
3424		{ "rgb32ui",			GL_RGB32UI,			},
3425		{ "rgb16f",				GL_RGB16F,			},
3426		{ "rgb16i",				GL_RGB16I,			},
3427		{ "rgb16ui",			GL_RGB16UI,			},
3428		{ "rgb8_snorm",			GL_RGB8_SNORM,		},
3429		{ "rgb8i",				GL_RGB8I,			},
3430		{ "rgb8ui",				GL_RGB8UI,			},
3431		{ "srgb8",				GL_SRGB8,			},
3432		{ "rgb9_e5",			GL_RGB9_E5,			},
3433		{ "rg32f",				GL_RG32F,			},
3434		{ "rg32i",				GL_RG32I,			},
3435		{ "rg32ui",				GL_RG32UI,			},
3436		{ "rg16f",				GL_RG16F,			},
3437		{ "rg16i",				GL_RG16I,			},
3438		{ "rg16ui",				GL_RG16UI,			},
3439		{ "rg8",				GL_RG8,				},
3440		{ "rg8i",				GL_RG8I,			},
3441		{ "rg8ui",				GL_RG8UI,			},
3442		{ "rg8_snorm",			GL_RG8_SNORM,		},
3443		{ "r32f",				GL_R32F,			},
3444		{ "r32i",				GL_R32I,			},
3445		{ "r32ui",				GL_R32UI,			},
3446		{ "r16f",				GL_R16F,			},
3447		{ "r16i",				GL_R16I,			},
3448		{ "r16ui",				GL_R16UI,			},
3449		{ "r8",					GL_R8,				},
3450		{ "r8i",				GL_R8I,				},
3451		{ "r8ui",				GL_R8UI,			},
3452		{ "r8_snorm",			GL_R8_SNORM,		}
3453	};
3454
3455	static const struct
3456	{
3457		const char*	name;
3458		deUint32	internalFormat;
3459	} depthStencilFormats[] =
3460	{
3461		// Depth and stencil formats
3462		{ "depth_component32f",	GL_DEPTH_COMPONENT32F	},
3463		{ "depth_component24",	GL_DEPTH_COMPONENT24	},
3464		{ "depth_component16",	GL_DEPTH_COMPONENT16	},
3465		{ "depth32f_stencil8",	GL_DEPTH32F_STENCIL8	},
3466		{ "depth24_stencil8",	GL_DEPTH24_STENCIL8		}
3467	};
3468
3469	// Basic TexImage2D usage.
3470	{
3471		tcu::TestCaseGroup* basicTexImageGroup = new tcu::TestCaseGroup(m_testCtx, "basic_teximage2d", "Basic glTexImage2D() usage");
3472		addChild(basicTexImageGroup);
3473		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
3474		{
3475			const char*	fmtName		= colorFormats[formatNdx].name;
3476			deUint32	format		= colorFormats[formatNdx].internalFormat;
3477			const int	tex2DWidth	= 64;
3478			const int	tex2DHeight	= 128;
3479			const int	texCubeSize	= 64;
3480
3481			basicTexImageGroup->addChild(new BasicTexImage2DCase	(m_context,	(string(fmtName) + "_2d").c_str(),		"",	format, tex2DWidth, tex2DHeight));
3482			basicTexImageGroup->addChild(new BasicTexImageCubeCase	(m_context,	(string(fmtName) + "_cube").c_str(),	"",	format, texCubeSize));
3483		}
3484	}
3485
3486	// Randomized TexImage2D order.
3487	{
3488		tcu::TestCaseGroup* randomTexImageGroup = new tcu::TestCaseGroup(m_testCtx, "random_teximage2d", "Randomized glTexImage2D() usage");
3489		addChild(randomTexImageGroup);
3490
3491		de::Random rnd(9);
3492
3493		// 2D cases.
3494		for (int ndx = 0; ndx < 10; ndx++)
3495		{
3496			int		formatNdx	= rnd.getInt(0, DE_LENGTH_OF_ARRAY(colorFormats)-1);
3497			int		width		= 1 << rnd.getInt(2, 8);
3498			int		height		= 1 << rnd.getInt(2, 8);
3499
3500			randomTexImageGroup->addChild(new RandomOrderTexImage2DCase(m_context, (string("2d_") + de::toString(ndx)).c_str(), "", colorFormats[formatNdx].internalFormat, width, height));
3501		}
3502
3503		// Cubemap cases.
3504		for (int ndx = 0; ndx < 10; ndx++)
3505		{
3506			int		formatNdx	= rnd.getInt(0, DE_LENGTH_OF_ARRAY(colorFormats)-1);
3507			int		size		= 1 << rnd.getInt(2, 8);
3508
3509			randomTexImageGroup->addChild(new RandomOrderTexImageCubeCase(m_context, (string("cube_") + de::toString(ndx)).c_str(), "", colorFormats[formatNdx].internalFormat, size));
3510		}
3511	}
3512
3513	// TexImage2D unpack alignment.
3514	{
3515		tcu::TestCaseGroup* alignGroup = new tcu::TestCaseGroup(m_testCtx, "teximage2d_align", "glTexImage2D() unpack alignment tests");
3516		addChild(alignGroup);
3517
3518		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_r8_4_8",			"",	GL_R8,			 4,  8, 4, 8));
3519		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_r8_63_1",			"",	GL_R8,			63, 30, 1, 1));
3520		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_r8_63_2",			"",	GL_R8,			63, 30, 1, 2));
3521		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_r8_63_4",			"",	GL_R8,			63, 30, 1, 4));
3522		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_r8_63_8",			"",	GL_R8,			63, 30, 1, 8));
3523		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgba4_51_1",		"",	GL_RGBA4,		51, 30, 1, 1));
3524		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgba4_51_2",		"",	GL_RGBA4,		51, 30, 1, 2));
3525		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgba4_51_4",		"",	GL_RGBA4,		51, 30, 1, 4));
3526		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgba4_51_8",		"",	GL_RGBA4,		51, 30, 1, 8));
3527		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgb8_39_1",			"",	GL_RGB8,		39, 43, 1, 1));
3528		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgb8_39_2",			"",	GL_RGB8,		39, 43, 1, 2));
3529		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgb8_39_4",			"",	GL_RGB8,		39, 43, 1, 4));
3530		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgb8_39_8",			"",	GL_RGB8,		39, 43, 1, 8));
3531		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgba8_47_1",		"",	GL_RGBA8,		47, 27, 1, 1));
3532		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgba8_47_2",		"",	GL_RGBA8,		47, 27, 1, 2));
3533		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgba8_47_4",		"",	GL_RGBA8,		47, 27, 1, 4));
3534		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgba8_47_8",		"",	GL_RGBA8,		47, 27, 1, 8));
3535
3536		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_r8_4_8",			"",	GL_R8,			 4, 3, 8));
3537		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_r8_63_1",			"",	GL_R8,			63, 1, 1));
3538		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_r8_63_2",			"",	GL_R8,			63, 1, 2));
3539		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_r8_63_4",			"",	GL_R8,			63, 1, 4));
3540		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_r8_63_8",			"",	GL_R8,			63, 1, 8));
3541		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgba4_51_1",		"",	GL_RGBA4,		51, 1, 1));
3542		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgba4_51_2",		"",	GL_RGBA4,		51, 1, 2));
3543		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgba4_51_4",		"",	GL_RGBA4,		51, 1, 4));
3544		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgba4_51_8",		"",	GL_RGBA4,		51, 1, 8));
3545		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgb8_39_1",		"",	GL_RGB8,		39, 1, 1));
3546		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgb8_39_2",		"",	GL_RGB8,		39, 1, 2));
3547		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgb8_39_4",		"",	GL_RGB8,		39, 1, 4));
3548		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgb8_39_8",		"",	GL_RGB8,		39, 1, 8));
3549		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgba8_47_1",		"",	GL_RGBA8,		47, 1, 1));
3550		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgba8_47_2",		"",	GL_RGBA8,		47, 1, 2));
3551		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgba8_47_4",		"",	GL_RGBA8,		47, 1, 4));
3552		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgba8_47_8",		"",	GL_RGBA8,		47, 1, 8));
3553	}
3554
3555	// glTexImage2D() unpack parameter cases.
3556	{
3557		tcu::TestCaseGroup* paramGroup = new tcu::TestCaseGroup(m_testCtx, "teximage2d_unpack_params", "glTexImage2D() pixel transfer mode cases");
3558		addChild(paramGroup);
3559
3560		static const struct
3561		{
3562			const char*	name;
3563			deUint32	format;
3564			int			width;
3565			int			height;
3566			int			rowLength;
3567			int			skipRows;
3568			int			skipPixels;
3569			int			alignment;
3570		} cases[] =
3571		{
3572			{ "rgb8_alignment",		GL_RGB8,	31,	30,	0,	0,	0,	2 },
3573			{ "rgb8_row_length",	GL_RGB8,	31,	30,	50,	0,	0,	4 },
3574			{ "rgb8_skip_rows",		GL_RGB8,	31,	30,	0,	3,	0,	4 },
3575			{ "rgb8_skip_pixels",	GL_RGB8,	31,	30,	36,	0,	5,	4 },
3576			{ "r8_complex1",		GL_R8,		31, 30, 64, 1,	3,	1 },
3577			{ "r8_complex2",		GL_R8,		31, 30, 64, 1,	3,	2 },
3578			{ "r8_complex3",		GL_R8,		31, 30, 64, 1,	3,	4 },
3579			{ "r8_complex4",		GL_R8,		31, 30, 64, 1,	3,	8 },
3580			{ "rgba8_complex1",		GL_RGBA8,	56,	61,	69,	0,	0,	8 },
3581			{ "rgba8_complex2",		GL_RGBA8,	56,	61,	69,	0,	7,	8 },
3582			{ "rgba8_complex3",		GL_RGBA8,	56,	61,	69,	3,	0,	8 },
3583			{ "rgba8_complex4",		GL_RGBA8,	56,	61,	69,	3,	7,	8 },
3584			{ "rgba32f_complex",	GL_RGBA32F,	19,	10,	27,	1,	7,	8 }
3585		};
3586
3587		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
3588			paramGroup->addChild(new TexImage2DParamsCase(m_context, cases[ndx].name, "",
3589														  cases[ndx].format,
3590														  cases[ndx].width,
3591														  cases[ndx].height,
3592														  cases[ndx].rowLength,
3593														  cases[ndx].skipRows,
3594														  cases[ndx].skipPixels,
3595														  cases[ndx].alignment));
3596	}
3597
3598	// glTexImage2D() pbo cases.
3599	{
3600		tcu::TestCaseGroup* pboGroup = new tcu::TestCaseGroup(m_testCtx, "teximage2d_pbo", "glTexImage2D() from PBO");
3601		addChild(pboGroup);
3602
3603		// Parameter cases
3604		static const struct
3605		{
3606			const char*	name;
3607			deUint32	format;
3608			int			width;
3609			int			height;
3610			int			rowLength;
3611			int			skipRows;
3612			int			skipPixels;
3613			int			alignment;
3614			int			offset;
3615		} parameterCases[] =
3616		{
3617			{ "rgb8_offset",		GL_RGB8,	31,	30,	0,	0,	0,	4,	67 },
3618			{ "rgb8_alignment",		GL_RGB8,	31,	30,	0,	0,	0,	2,	0 },
3619			{ "rgb8_row_length",	GL_RGB8,	31,	30,	50,	0,	0,	4,	0 },
3620			{ "rgb8_skip_rows",		GL_RGB8,	31,	30,	0,	3,	0,	4,	0 },
3621			{ "rgb8_skip_pixels",	GL_RGB8,	31,	30,	36,	0,	5,	4,	0 }
3622		};
3623
3624		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
3625		{
3626			const string	fmtName		= colorFormats[formatNdx].name;
3627			const deUint32	format		= colorFormats[formatNdx].internalFormat;
3628			const int		tex2DWidth	= 65;
3629			const int		tex2DHeight	= 37;
3630			const int		texCubeSize	= 64;
3631
3632			pboGroup->addChild(new TexImage2DBufferCase		(m_context,	(fmtName + "_2d").c_str(),		"", format, tex2DWidth, tex2DHeight, 0, 0, 0, 4, 0));
3633			pboGroup->addChild(new TexImageCubeBufferCase	(m_context,	(fmtName + "_cube").c_str(),	"", format, texCubeSize, 0, 0, 0, 4, 0));
3634		}
3635
3636		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(parameterCases); ndx++)
3637		{
3638			pboGroup->addChild(new TexImage2DBufferCase(m_context, (string(parameterCases[ndx].name) + "_2d").c_str(), "",
3639														parameterCases[ndx].format,
3640														parameterCases[ndx].width,
3641														parameterCases[ndx].height,
3642														parameterCases[ndx].rowLength,
3643														parameterCases[ndx].skipRows,
3644														parameterCases[ndx].skipPixels,
3645														parameterCases[ndx].alignment,
3646														parameterCases[ndx].offset));
3647			pboGroup->addChild(new TexImageCubeBufferCase(m_context, (string(parameterCases[ndx].name) + "_cube").c_str(), "",
3648														parameterCases[ndx].format,
3649														parameterCases[ndx].width,
3650														parameterCases[ndx].rowLength,
3651														parameterCases[ndx].skipRows,
3652														parameterCases[ndx].skipPixels,
3653														parameterCases[ndx].alignment,
3654														parameterCases[ndx].offset));
3655		}
3656	}
3657
3658	// glTexImage2D() depth cases.
3659	{
3660		tcu::TestCaseGroup* shadow2dGroup = new tcu::TestCaseGroup(m_testCtx, "teximage2d_depth", "glTexImage2D() with depth or depth/stencil format");
3661		addChild(shadow2dGroup);
3662
3663		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
3664		{
3665			const int tex2DWidth	= 64;
3666			const int tex2DHeight	= 128;
3667
3668			shadow2dGroup->addChild(new TexImage2DDepthCase(m_context, depthStencilFormats[ndx].name, "", depthStencilFormats[ndx].internalFormat, tex2DWidth, tex2DHeight));
3669		}
3670	}
3671
3672	// glTexImage2D() depth cases with pbo.
3673	{
3674		tcu::TestCaseGroup* shadow2dGroup = new tcu::TestCaseGroup(m_testCtx, "teximage2d_depth_pbo", "glTexImage2D() with depth or depth/stencil format with pbo");
3675		addChild(shadow2dGroup);
3676
3677		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
3678		{
3679			const int tex2DWidth	= 64;
3680			const int tex2DHeight	= 128;
3681
3682			shadow2dGroup->addChild(new TexImage2DDepthBufferCase(m_context, depthStencilFormats[ndx].name, "", depthStencilFormats[ndx].internalFormat, tex2DWidth, tex2DHeight));
3683		}
3684	}
3685
3686	// Basic TexSubImage2D usage.
3687	{
3688		tcu::TestCaseGroup* basicTexSubImageGroup = new tcu::TestCaseGroup(m_testCtx, "basic_texsubimage2d", "Basic glTexSubImage2D() usage");
3689		addChild(basicTexSubImageGroup);
3690		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
3691		{
3692			const char*	fmtName		= colorFormats[formatNdx].name;
3693			deUint32	format		= colorFormats[formatNdx].internalFormat;
3694			const int	tex2DWidth	= 64;
3695			const int	tex2DHeight	= 128;
3696			const int	texCubeSize	= 64;
3697
3698			basicTexSubImageGroup->addChild(new BasicTexSubImage2DCase		(m_context,	(string(fmtName) + "_2d").c_str(),		"",	format, tex2DWidth, tex2DHeight));
3699			basicTexSubImageGroup->addChild(new BasicTexSubImageCubeCase	(m_context,	(string(fmtName) + "_cube").c_str(),	"",	format, texCubeSize));
3700		}
3701	}
3702
3703	// TexSubImage2D to empty texture.
3704	{
3705		tcu::TestCaseGroup* texSubImageEmptyTexGroup = new tcu::TestCaseGroup(m_testCtx, "texsubimage2d_empty_tex", "glTexSubImage2D() to texture that has storage but no data");
3706		addChild(texSubImageEmptyTexGroup);
3707		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(unsizedFormats); formatNdx++)
3708		{
3709			const char*	fmtName		= unsizedFormats[formatNdx].name;
3710			deUint32	format		= unsizedFormats[formatNdx].format;
3711			deUint32	dataType	= unsizedFormats[formatNdx].dataType;
3712			const int	tex2DWidth	= 64;
3713			const int	tex2DHeight	= 32;
3714			const int	texCubeSize	= 32;
3715
3716			texSubImageEmptyTexGroup->addChild(new TexSubImage2DEmptyTexCase	(m_context,	(string(fmtName) + "_2d").c_str(),		"",	format, dataType, tex2DWidth, tex2DHeight));
3717			texSubImageEmptyTexGroup->addChild(new TexSubImageCubeEmptyTexCase	(m_context,	(string(fmtName) + "_cube").c_str(),	"",	format, dataType, texCubeSize));
3718		}
3719	}
3720
3721	// TexSubImage2D alignment cases.
3722	{
3723		tcu::TestCaseGroup* alignGroup = new tcu::TestCaseGroup(m_testCtx, "texsubimage2d_align", "glTexSubImage2D() unpack alignment tests");
3724		addChild(alignGroup);
3725
3726		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_r8_1_1",			"",	GL_R8,			64, 64, 13, 17,  1,  6, 1));
3727		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_r8_1_2",			"",	GL_R8,			64, 64, 13, 17,  1,  6, 2));
3728		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_r8_1_4",			"",	GL_R8,			64, 64, 13, 17,  1,  6, 4));
3729		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_r8_1_8",			"",	GL_R8,			64, 64, 13, 17,  1,  6, 8));
3730		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_r8_63_1",			"",	GL_R8,			64, 64,  1,  9, 63, 30, 1));
3731		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_r8_63_2",			"",	GL_R8,			64, 64,  1,  9, 63, 30, 2));
3732		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_r8_63_4",			"",	GL_R8,			64, 64,  1,  9, 63, 30, 4));
3733		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_r8_63_8",			"",	GL_R8,			64, 64,  1,  9, 63, 30, 8));
3734		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgba4_51_1",		"",	GL_RGBA4,		64, 64,  7, 29, 51, 30, 1));
3735		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgba4_51_2",		"",	GL_RGBA4,		64, 64,  7, 29, 51, 30, 2));
3736		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgba4_51_4",		"",	GL_RGBA4,		64, 64,  7, 29, 51, 30, 4));
3737		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgba4_51_8",		"",	GL_RGBA4,		64, 64,  7, 29, 51, 30, 8));
3738		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgb8_39_1",			"",	GL_RGB8,		64, 64, 11,  8, 39, 43, 1));
3739		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgb8_39_2",			"",	GL_RGB8,		64, 64, 11,  8, 39, 43, 2));
3740		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgb8_39_4",			"",	GL_RGB8,		64, 64, 11,  8, 39, 43, 4));
3741		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgb8_39_8",			"",	GL_RGB8,		64, 64, 11,  8, 39, 43, 8));
3742		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgba8_47_1",		"",	GL_RGBA8,		64, 64, 10,  1, 47, 27, 1));
3743		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgba8_47_2",		"",	GL_RGBA8,		64, 64, 10,  1, 47, 27, 2));
3744		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgba8_47_4",		"",	GL_RGBA8,		64, 64, 10,  1, 47, 27, 4));
3745		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgba8_47_8",		"",	GL_RGBA8,		64, 64, 10,  1, 47, 27, 8));
3746
3747		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_r8_1_1",			"",	GL_R8,			64, 13, 17,  1,  6, 1));
3748		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_r8_1_2",			"",	GL_R8,			64, 13, 17,  1,  6, 2));
3749		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_r8_1_4",			"",	GL_R8,			64, 13, 17,  1,  6, 4));
3750		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_r8_1_8",			"",	GL_R8,			64, 13, 17,  1,  6, 8));
3751		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_r8_63_1",			"",	GL_R8,			64,  1,  9, 63, 30, 1));
3752		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_r8_63_2",			"",	GL_R8,			64,  1,  9, 63, 30, 2));
3753		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_r8_63_4",			"",	GL_R8,			64,  1,  9, 63, 30, 4));
3754		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_r8_63_8",			"",	GL_R8,			64,  1,  9, 63, 30, 8));
3755		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgba4_51_1",		"",	GL_RGBA4,		64,  7, 29, 51, 30, 1));
3756		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgba4_51_2",		"",	GL_RGBA4,		64,  7, 29, 51, 30, 2));
3757		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgba4_51_4",		"",	GL_RGBA4,		64,  7, 29, 51, 30, 4));
3758		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgba4_51_8",		"",	GL_RGBA4,		64,  7, 29, 51, 30, 8));
3759		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgb8_39_1",		"",	GL_RGB8,		64, 11,  8, 39, 43, 1));
3760		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgb8_39_2",		"",	GL_RGB8,		64, 11,  8, 39, 43, 2));
3761		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgb8_39_4",		"",	GL_RGB8,		64, 11,  8, 39, 43, 4));
3762		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgb8_39_8",		"",	GL_RGB8,		64, 11,  8, 39, 43, 8));
3763		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgba8_47_1",		"",	GL_RGBA8,		64, 10,  1, 47, 27, 1));
3764		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgba8_47_2",		"",	GL_RGBA8,		64, 10,  1, 47, 27, 2));
3765		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgba8_47_4",		"",	GL_RGBA8,		64, 10,  1, 47, 27, 4));
3766		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgba8_47_8",		"",	GL_RGBA8,		64, 10,  1, 47, 27, 8));
3767	}
3768
3769	// glTexSubImage2D() pixel transfer mode cases.
3770	{
3771		tcu::TestCaseGroup* paramGroup = new tcu::TestCaseGroup(m_testCtx, "texsubimage2d_unpack_params", "glTexSubImage2D() pixel transfer mode cases");
3772		addChild(paramGroup);
3773
3774		static const struct
3775		{
3776			const char*	name;
3777			deUint32	format;
3778			int			width;
3779			int			height;
3780			int			subX;
3781			int			subY;
3782			int			subW;
3783			int			subH;
3784			int			rowLength;
3785			int			skipRows;
3786			int			skipPixels;
3787			int			alignment;
3788		} cases[] =
3789		{
3790			{ "rgb8_alignment",		GL_RGB8,	54,	60,	11,	7,	31,	30,	0,	0,	0,	2 },
3791			{ "rgb8_row_length",	GL_RGB8,	54,	60,	11,	7,	31,	30,	50,	0,	0,	4 },
3792			{ "rgb8_skip_rows",		GL_RGB8,	54,	60,	11,	7,	31,	30,	0,	3,	0,	4 },
3793			{ "rgb8_skip_pixels",	GL_RGB8,	54,	60,	11,	7,	31,	30,	36,	0,	5,	4 },
3794			{ "r8_complex1",		GL_R8,		54,	60,	11,	7,	31, 30, 64, 1,	3,	1 },
3795			{ "r8_complex2",		GL_R8,		54,	60,	11,	7,	31, 30, 64, 1,	3,	2 },
3796			{ "r8_complex3",		GL_R8,		54,	60,	11,	7,	31, 30, 64, 1,	3,	4 },
3797			{ "r8_complex4",		GL_R8,		54,	60,	11,	7,	31, 30, 64, 1,	3,	8 },
3798			{ "rgba8_complex1",		GL_RGBA8,	92,	84,	13,	19,	56,	61,	69,	0,	0,	8 },
3799			{ "rgba8_complex2",		GL_RGBA8,	92,	84,	13,	19,	56,	61,	69,	0,	7,	8 },
3800			{ "rgba8_complex3",		GL_RGBA8,	92,	84,	13,	19,	56,	61,	69,	3,	0,	8 },
3801			{ "rgba8_complex4",		GL_RGBA8,	92,	84,	13,	19,	56,	61,	69,	3,	7,	8 },
3802			{ "rgba32f_complex",	GL_RGBA32F,	92,	84,	13,	19,	56,	61,	69,	3,	7,	8 }
3803		};
3804
3805		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
3806			paramGroup->addChild(new TexSubImage2DParamsCase(m_context, cases[ndx].name, "",
3807															 cases[ndx].format,
3808															 cases[ndx].width,
3809															 cases[ndx].height,
3810															 cases[ndx].subX,
3811															 cases[ndx].subY,
3812															 cases[ndx].subW,
3813															 cases[ndx].subH,
3814															 cases[ndx].rowLength,
3815															 cases[ndx].skipRows,
3816															 cases[ndx].skipPixels,
3817															 cases[ndx].alignment));
3818	}
3819
3820	// glTexSubImage2D() PBO cases.
3821	{
3822		tcu::TestCaseGroup* pboGroup = new tcu::TestCaseGroup(m_testCtx, "texsubimage2d_pbo", "glTexSubImage2D() pixel buffer object tests");
3823		addChild(pboGroup);
3824
3825		static const struct
3826		{
3827			const char*	name;
3828			deUint32	format;
3829			int			width;
3830			int			height;
3831			int			subX;
3832			int			subY;
3833			int			subW;
3834			int			subH;
3835			int			rowLength;
3836			int			skipRows;
3837			int			skipPixels;
3838			int			alignment;
3839			int			offset;
3840		} paramCases[] =
3841		{
3842			{ "rgb8_offset",		GL_RGB8,	54,	60,	11,	7,	31,	30,	0,	0,	0,	4,	67 },
3843			{ "rgb8_alignment",		GL_RGB8,	54,	60,	11,	7,	31,	30,	0,	0,	0,	2,	0 },
3844			{ "rgb8_row_length",	GL_RGB8,	54,	60,	11,	7,	31,	30,	50,	0,	0,	4,	0 },
3845			{ "rgb8_skip_rows",		GL_RGB8,	54,	60,	11,	7,	31,	30,	0,	3,	0,	4,	0 },
3846			{ "rgb8_skip_pixels",	GL_RGB8,	54,	60,	11,	7,	31,	30,	36,	0,	5,	4,	0 }
3847		};
3848
3849		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++)
3850		{
3851			pboGroup->addChild(new TexSubImage2DBufferCase(m_context, (std::string(colorFormats[ndx].name) + "_2d").c_str(), "",
3852														   colorFormats[ndx].internalFormat,
3853														   54,	// Width
3854														   60,	// Height
3855														   11,	// Sub X
3856														   7,	// Sub Y
3857														   31,	// Sub W
3858														   30,	// Sub H
3859														   0,	// Row len
3860														   0,	// Skip rows
3861														   0,	// Skip pixels
3862														   4,	// Alignment
3863														   0	/* offset */));
3864			pboGroup->addChild(new TexSubImageCubeBufferCase(m_context, (std::string(colorFormats[ndx].name) + "_cube").c_str(), "",
3865														   colorFormats[ndx].internalFormat,
3866														   64,	// Size
3867														   11,	// Sub X
3868														   7,	// Sub Y
3869														   31,	// Sub W
3870														   30,	// Sub H
3871														   0,	// Row len
3872														   0,	// Skip rows
3873														   0,	// Skip pixels
3874														   4,	// Alignment
3875														   0	/* offset */));
3876		}
3877
3878		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(paramCases); ndx++)
3879		{
3880			pboGroup->addChild(new TexSubImage2DBufferCase(m_context, (std::string(paramCases[ndx].name) + "_2d").c_str(), "",
3881														   paramCases[ndx].format,
3882														   paramCases[ndx].width,
3883														   paramCases[ndx].height,
3884														   paramCases[ndx].subX,
3885														   paramCases[ndx].subY,
3886														   paramCases[ndx].subW,
3887														   paramCases[ndx].subH,
3888														   paramCases[ndx].rowLength,
3889														   paramCases[ndx].skipRows,
3890														   paramCases[ndx].skipPixels,
3891														   paramCases[ndx].alignment,
3892														   paramCases[ndx].offset));
3893			pboGroup->addChild(new TexSubImageCubeBufferCase(m_context, (std::string(paramCases[ndx].name) + "_cube").c_str(), "",
3894														   paramCases[ndx].format,
3895														   paramCases[ndx].width,
3896														   paramCases[ndx].subX,
3897														   paramCases[ndx].subY,
3898														   paramCases[ndx].subW,
3899														   paramCases[ndx].subH,
3900														   paramCases[ndx].rowLength,
3901														   paramCases[ndx].skipRows,
3902														   paramCases[ndx].skipPixels,
3903														   paramCases[ndx].alignment,
3904														   paramCases[ndx].offset));
3905		}
3906	}
3907
3908	// glTexSubImage2D() depth cases.
3909	{
3910		tcu::TestCaseGroup* shadow2dGroup = new tcu::TestCaseGroup(m_testCtx, "texsubimage2d_depth", "glTexSubImage2D() with depth or depth/stencil format");
3911		addChild(shadow2dGroup);
3912
3913		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
3914		{
3915			const int	tex2DWidth	= 64;
3916			const int	tex2DHeight	= 32;
3917
3918			shadow2dGroup->addChild(new TexSubImage2DDepthCase(m_context, depthStencilFormats[ndx].name, "", depthStencilFormats[ndx].internalFormat, tex2DWidth, tex2DHeight));
3919		}
3920	}
3921
3922	// Basic glCopyTexImage2D() cases
3923	{
3924		tcu::TestCaseGroup* copyTexImageGroup = new tcu::TestCaseGroup(m_testCtx, "basic_copyteximage2d", "Basic glCopyTexImage2D() usage");
3925		addChild(copyTexImageGroup);
3926
3927		copyTexImageGroup->addChild(new BasicCopyTexImage2DCase		(m_context, "2d_alpha",				"",	GL_ALPHA,			128, 64));
3928		copyTexImageGroup->addChild(new BasicCopyTexImage2DCase		(m_context, "2d_luminance",			"",	GL_LUMINANCE,		128, 64));
3929		copyTexImageGroup->addChild(new BasicCopyTexImage2DCase		(m_context, "2d_luminance_alpha",	"",	GL_LUMINANCE_ALPHA,	128, 64));
3930		copyTexImageGroup->addChild(new BasicCopyTexImage2DCase		(m_context, "2d_rgb",				"",	GL_RGB,				128, 64));
3931		copyTexImageGroup->addChild(new BasicCopyTexImage2DCase		(m_context, "2d_rgba",				"",	GL_RGBA,			128, 64));
3932
3933		copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase	(m_context, "cube_alpha",			"",	GL_ALPHA,			64));
3934		copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase	(m_context, "cube_luminance",		"",	GL_LUMINANCE,		64));
3935		copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase	(m_context, "cube_luminance_alpha",	"",	GL_LUMINANCE_ALPHA,	64));
3936		copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase	(m_context, "cube_rgb",				"",	GL_RGB,				64));
3937		copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase	(m_context, "cube_rgba",			"",	GL_RGBA,			64));
3938	}
3939
3940	// Basic glCopyTexSubImage2D() cases
3941	{
3942		tcu::TestCaseGroup* copyTexSubImageGroup = new tcu::TestCaseGroup(m_testCtx, "basic_copytexsubimage2d", "Basic glCopyTexSubImage2D() usage");
3943		addChild(copyTexSubImageGroup);
3944
3945		copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase	(m_context, "2d_alpha",				"",	GL_ALPHA,			GL_UNSIGNED_BYTE, 128, 64));
3946		copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase	(m_context, "2d_luminance",			"",	GL_LUMINANCE,		GL_UNSIGNED_BYTE, 128, 64));
3947		copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase	(m_context, "2d_luminance_alpha",	"",	GL_LUMINANCE_ALPHA,	GL_UNSIGNED_BYTE, 128, 64));
3948		copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase	(m_context, "2d_rgb",				"",	GL_RGB,				GL_UNSIGNED_BYTE, 128, 64));
3949		copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase	(m_context, "2d_rgba",				"",	GL_RGBA,			GL_UNSIGNED_BYTE, 128, 64));
3950
3951		copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase	(m_context, "cube_alpha",			"",	GL_ALPHA,			GL_UNSIGNED_BYTE, 64));
3952		copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase	(m_context, "cube_luminance",		"",	GL_LUMINANCE,		GL_UNSIGNED_BYTE, 64));
3953		copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase	(m_context, "cube_luminance_alpha",	"",	GL_LUMINANCE_ALPHA,	GL_UNSIGNED_BYTE, 64));
3954		copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase	(m_context, "cube_rgb",				"",	GL_RGB,				GL_UNSIGNED_BYTE, 64));
3955		copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase	(m_context, "cube_rgba",			"",	GL_RGBA,			GL_UNSIGNED_BYTE, 64));
3956	}
3957
3958	// Basic TexImage3D usage.
3959	{
3960		tcu::TestCaseGroup* basicTexImageGroup = new tcu::TestCaseGroup(m_testCtx, "basic_teximage3d", "Basic glTexImage3D() usage");
3961		addChild(basicTexImageGroup);
3962		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
3963		{
3964			const char*	fmtName				= colorFormats[formatNdx].name;
3965			deUint32	format				= colorFormats[formatNdx].internalFormat;
3966			const int	tex2DArrayWidth		= 57;
3967			const int	tex2DArrayHeight	= 44;
3968			const int	tex2DArrayLevels	= 5;
3969			const int	tex3DWidth			= 63;
3970			const int	tex3DHeight			= 29;
3971			const int	tex3DDepth			= 11;
3972
3973			basicTexImageGroup->addChild(new BasicTexImage2DArrayCase	(m_context,	(string(fmtName) + "_2d_array").c_str(),	"",	format, tex2DArrayWidth, tex2DArrayHeight, tex2DArrayLevels));
3974			basicTexImageGroup->addChild(new BasicTexImage3DCase		(m_context,	(string(fmtName) + "_3d").c_str(),			"",	format, tex3DWidth, tex3DHeight, tex3DDepth));
3975		}
3976	}
3977
3978	// glTexImage3D() unpack params cases.
3979	{
3980		tcu::TestCaseGroup* paramGroup = new tcu::TestCaseGroup(m_testCtx, "teximage3d_unpack_params", "glTexImage3D() unpack parameters");
3981		addChild(paramGroup);
3982
3983		static const struct
3984		{
3985			const char*	name;
3986			deUint32	format;
3987			int			width;
3988			int			height;
3989			int			depth;
3990			int			imageHeight;
3991			int			rowLength;
3992			int			skipImages;
3993			int			skipRows;
3994			int			skipPixels;
3995			int			alignment;
3996		} cases[] =
3997		{
3998			{ "rgb8_image_height",	GL_RGB8,	23,	19,	8,	26,	0,	0,	0,	0,	4 },
3999			{ "rgb8_row_length",	GL_RGB8,	23,	19,	8,	0,	27,	0,	0,	0,	4 },
4000			{ "rgb8_skip_images",	GL_RGB8,	23,	19,	8,	0,	0,	3,	0,	0,	4 },
4001			{ "rgb8_skip_rows",		GL_RGB8,	23,	19,	8,	22,	0,	0,	3,	0,	4 },
4002			{ "rgb8_skip_pixels",	GL_RGB8,	23,	19,	8,	0,	25,	0,	0,	2,	4 },
4003			{ "r8_complex1",		GL_R8,		13, 17, 11,	23,	15,	2,	3,	1,	1 },
4004			{ "r8_complex2",		GL_R8,		13, 17, 11,	23,	15,	2,	3,	1,	2 },
4005			{ "r8_complex3",		GL_R8,		13, 17, 11,	23,	15,	2,	3,	1,	4 },
4006			{ "r8_complex4",		GL_R8,		13, 17, 11,	23,	15,	2,	3,	1,	8 },
4007			{ "rgba8_complex1",		GL_RGBA8,	11,	20,	8,	25,	14,	0,	0,	0,	8 },
4008			{ "rgba8_complex2",		GL_RGBA8,	11,	20,	8,	25,	14,	0,	2,	0,	8 },
4009			{ "rgba8_complex3",		GL_RGBA8,	11,	20,	8,	25,	14,	0,	0,	3,	8 },
4010			{ "rgba8_complex4",		GL_RGBA8,	11,	20,	8,	25,	14,	0,	2,	3,	8 },
4011			{ "rgba32f_complex",	GL_RGBA32F,	11,	20,	8,	25,	14,	0,	2,	3,	8 }
4012		};
4013
4014		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
4015			paramGroup->addChild(new TexImage3DParamsCase(m_context, cases[ndx].name, "",
4016														  cases[ndx].format,
4017														  cases[ndx].width,
4018														  cases[ndx].height,
4019														  cases[ndx].depth,
4020														  cases[ndx].imageHeight,
4021														  cases[ndx].rowLength,
4022														  cases[ndx].skipImages,
4023														  cases[ndx].skipRows,
4024														  cases[ndx].skipPixels,
4025														  cases[ndx].alignment));
4026	}
4027
4028	// glTexImage3D() pbo cases.
4029	{
4030		tcu::TestCaseGroup* pboGroup = new tcu::TestCaseGroup(m_testCtx, "teximage3d_pbo", "glTexImage3D() from PBO");
4031		addChild(pboGroup);
4032
4033		// Parameter cases
4034		static const struct
4035		{
4036			const char*	name;
4037			deUint32	format;
4038			int			width;
4039			int			height;
4040			int			depth;
4041			int			imageHeight;
4042			int			rowLength;
4043			int			skipImages;
4044			int			skipRows;
4045			int			skipPixels;
4046			int			alignment;
4047			int			offset;
4048		} parameterCases[] =
4049		{
4050			{ "rgb8_offset",		GL_RGB8,	23,	19,	8,	0,	0,	0,	0,	0,	1,	67 },
4051			{ "rgb8_alignment",		GL_RGB8,	23,	19,	8,	0,	0,	0,	0,	0,	2,	0 },
4052			{ "rgb8_image_height",	GL_RGB8,	23,	19,	8,	26,	0,	0,	0,	0,	4,	0 },
4053			{ "rgb8_row_length",	GL_RGB8,	23,	19,	8,	0,	27,	0,	0,	0,	4,	0 },
4054			{ "rgb8_skip_images",	GL_RGB8,	23,	19,	8,	0,	0,	3,	0,	0,	4,	0 },
4055			{ "rgb8_skip_rows",		GL_RGB8,	23,	19,	8,	22,	0,	0,	3,	0,	4,	0 },
4056			{ "rgb8_skip_pixels",	GL_RGB8,	23,	19,	8,	0,	25,	0,	0,	2,	4,	0 }
4057		};
4058
4059		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
4060		{
4061			const string	fmtName		= colorFormats[formatNdx].name;
4062			const deUint32	format		= colorFormats[formatNdx].internalFormat;
4063			const int		tex3DWidth	= 11;
4064			const int		tex3DHeight	= 20;
4065			const int		tex3DDepth	= 8;
4066
4067			pboGroup->addChild(new TexImage2DArrayBufferCase	(m_context, (fmtName + "_2d_array").c_str(),	"", format, tex3DWidth, tex3DHeight, tex3DDepth, 0, 0, 0, 0, 0, 4, 0));
4068			pboGroup->addChild(new TexImage3DBufferCase			(m_context, (fmtName + "_3d").c_str(),			"", format, tex3DWidth, tex3DHeight, tex3DDepth, 0, 0, 0, 0, 0, 4, 0));
4069		}
4070
4071		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(parameterCases); ndx++)
4072		{
4073			pboGroup->addChild(new TexImage2DArrayBufferCase(m_context, (string(parameterCases[ndx].name) + "_2d_array").c_str(), "",
4074														parameterCases[ndx].format,
4075														parameterCases[ndx].width,
4076														parameterCases[ndx].depth,
4077														parameterCases[ndx].height,
4078														parameterCases[ndx].imageHeight,
4079														parameterCases[ndx].rowLength,
4080														parameterCases[ndx].skipImages,
4081														parameterCases[ndx].skipRows,
4082														parameterCases[ndx].skipPixels,
4083														parameterCases[ndx].alignment,
4084														parameterCases[ndx].offset));
4085			pboGroup->addChild(new TexImage3DBufferCase(m_context, (string(parameterCases[ndx].name) + "_3d").c_str(), "",
4086														parameterCases[ndx].format,
4087														parameterCases[ndx].width,
4088														parameterCases[ndx].depth,
4089														parameterCases[ndx].height,
4090														parameterCases[ndx].imageHeight,
4091														parameterCases[ndx].rowLength,
4092														parameterCases[ndx].skipImages,
4093														parameterCases[ndx].skipRows,
4094														parameterCases[ndx].skipPixels,
4095														parameterCases[ndx].alignment,
4096														parameterCases[ndx].offset));
4097		}
4098	}
4099
4100	// glTexImage3D() depth cases.
4101	{
4102		tcu::TestCaseGroup* shadow3dGroup = new tcu::TestCaseGroup(m_testCtx, "teximage3d_depth", "glTexImage3D() with depth or depth/stencil format");
4103		addChild(shadow3dGroup);
4104
4105		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
4106		{
4107			const int	tex3DWidth	= 32;
4108			const int	tex3DHeight	= 64;
4109			const int	tex3DDepth	= 8;
4110
4111			shadow3dGroup->addChild(new TexImage2DArrayDepthCase(m_context, (std::string(depthStencilFormats[ndx].name) + "_2d_array").c_str(), "", depthStencilFormats[ndx].internalFormat, tex3DWidth, tex3DHeight, tex3DDepth));
4112		}
4113	}
4114
4115	// glTexImage3D() depth cases with pbo.
4116	{
4117		tcu::TestCaseGroup* shadow3dGroup = new tcu::TestCaseGroup(m_testCtx, "teximage3d_depth_pbo", "glTexImage3D() with depth or depth/stencil format with pbo");
4118		addChild(shadow3dGroup);
4119
4120		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
4121		{
4122			const int	tex3DWidth	= 32;
4123			const int	tex3DHeight	= 64;
4124			const int	tex3DDepth	= 8;
4125
4126			shadow3dGroup->addChild(new TexImage2DArrayDepthBufferCase(m_context, (std::string(depthStencilFormats[ndx].name) + "_2d_array").c_str(), "", depthStencilFormats[ndx].internalFormat, tex3DWidth, tex3DHeight, tex3DDepth));
4127		}
4128	}
4129
4130	// Basic TexSubImage3D usage.
4131	{
4132		tcu::TestCaseGroup* basicTexSubImageGroup = new tcu::TestCaseGroup(m_testCtx, "basic_texsubimage3d", "Basic glTexSubImage3D() usage");
4133		addChild(basicTexSubImageGroup);
4134		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
4135		{
4136			const char*	fmtName		= colorFormats[formatNdx].name;
4137			deUint32	format		= colorFormats[formatNdx].internalFormat;
4138			const int	tex3DWidth	= 32;
4139			const int	tex3DHeight	= 64;
4140			const int	tex3DDepth	= 8;
4141
4142			basicTexSubImageGroup->addChild(new BasicTexSubImage3DCase(m_context, (string(fmtName) + "_3d").c_str(), "", format, tex3DWidth, tex3DHeight, tex3DDepth));
4143		}
4144	}
4145
4146	// glTexSubImage3D() unpack params cases.
4147	{
4148		tcu::TestCaseGroup* paramGroup = new tcu::TestCaseGroup(m_testCtx, "texsubimage3d_unpack_params", "glTexSubImage3D() unpack parameters");
4149		addChild(paramGroup);
4150
4151		static const struct
4152		{
4153			const char*	name;
4154			deUint32	format;
4155			int			width;
4156			int			height;
4157			int			depth;
4158			int			subX;
4159			int			subY;
4160			int			subZ;
4161			int			subW;
4162			int			subH;
4163			int			subD;
4164			int			imageHeight;
4165			int			rowLength;
4166			int			skipImages;
4167			int			skipRows;
4168			int			skipPixels;
4169			int			alignment;
4170		} cases[] =
4171		{
4172			{ "rgb8_image_height",	GL_RGB8,	26, 25, 10,	1,	2,	1,	23,	19,	8,	26,	0,	0,	0,	0,	4 },
4173			{ "rgb8_row_length",	GL_RGB8,	26, 25, 10,	1,	2,	1,	23,	19,	8,	0,	27,	0,	0,	0,	4 },
4174			{ "rgb8_skip_images",	GL_RGB8,	26, 25, 10,	1,	2,	1,	23,	19,	8,	0,	0,	3,	0,	0,	4 },
4175			{ "rgb8_skip_rows",		GL_RGB8,	26, 25, 10,	1,	2,	1,	23,	19,	8,	22,	0,	0,	3,	0,	4 },
4176			{ "rgb8_skip_pixels",	GL_RGB8,	26, 25, 10,	1,	2,	1,	23,	19,	8,	0,	25,	0,	0,	2,	4 },
4177			{ "r8_complex1",		GL_R8,		15,	20,	11,	1,	1,	0,	13, 17, 11,	23,	15,	2,	3,	1,	1 },
4178			{ "r8_complex2",		GL_R8,		15,	20,	11,	1,	1,	0,	13, 17, 11,	23,	15,	2,	3,	1,	2 },
4179			{ "r8_complex3",		GL_R8,		15,	20,	11,	1,	1,	0,	13, 17, 11,	23,	15,	2,	3,	1,	4 },
4180			{ "r8_complex4",		GL_R8,		15,	20,	11,	1,	1,	0,	13, 17, 11,	23,	15,	2,	3,	1,	8 },
4181			{ "rgba8_complex1",		GL_RGBA8,	15,	25,	10,	0,	5,	1,	11,	20,	8,	25,	14,	0,	0,	0,	8 },
4182			{ "rgba8_complex2",		GL_RGBA8,	15,	25,	10,	0,	5,	1,	11,	20,	8,	25,	14,	0,	2,	0,	8 },
4183			{ "rgba8_complex3",		GL_RGBA8,	15,	25,	10,	0,	5,	1,	11,	20,	8,	25,	14,	0,	0,	3,	8 },
4184			{ "rgba8_complex4",		GL_RGBA8,	15,	25,	10,	0,	5,	1,	11,	20,	8,	25,	14,	0,	2,	3,	8 },
4185			{ "rgba32f_complex",	GL_RGBA32F,	15,	25,	10,	0,	5,	1,	11,	20,	8,	25,	14,	0,	2,	3,	8 }
4186		};
4187
4188		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ndx++)
4189			paramGroup->addChild(new TexSubImage3DParamsCase(m_context, cases[ndx].name, "",
4190															 cases[ndx].format,
4191															 cases[ndx].width,
4192															 cases[ndx].height,
4193															 cases[ndx].depth,
4194															 cases[ndx].subX,
4195															 cases[ndx].subY,
4196															 cases[ndx].subZ,
4197															 cases[ndx].subW,
4198															 cases[ndx].subH,
4199															 cases[ndx].subD,
4200															 cases[ndx].imageHeight,
4201															 cases[ndx].rowLength,
4202															 cases[ndx].skipImages,
4203															 cases[ndx].skipRows,
4204															 cases[ndx].skipPixels,
4205															 cases[ndx].alignment));
4206	}
4207
4208	// glTexSubImage3D() PBO cases.
4209	{
4210		tcu::TestCaseGroup* pboGroup = new tcu::TestCaseGroup(m_testCtx, "texsubimage3d_pbo", "glTexSubImage3D() pixel buffer object tests");
4211		addChild(pboGroup);
4212
4213		static const struct
4214		{
4215			const char*	name;
4216			deUint32	format;
4217			int			width;
4218			int			height;
4219			int			depth;
4220			int			subX;
4221			int			subY;
4222			int			subZ;
4223			int			subW;
4224			int			subH;
4225			int			subD;
4226			int			imageHeight;
4227			int			rowLength;
4228			int			skipImages;
4229			int			skipRows;
4230			int			skipPixels;
4231			int			alignment;
4232			int			offset;
4233		} paramCases[] =
4234		{
4235			{ "rgb8_offset",		GL_RGB8,	26, 25, 10,	1,	2,	1,	23,	19,	8,	0,	0,	0,	0,	0,	4,	67 },
4236			{ "rgb8_image_height",	GL_RGB8,	26, 25, 10,	1,	2,	1,	23,	19,	8,	26,	0,	0,	0,	0,	4,	0 },
4237			{ "rgb8_row_length",	GL_RGB8,	26, 25, 10,	1,	2,	1,	23,	19,	8,	0,	27,	0,	0,	0,	4,	0 },
4238			{ "rgb8_skip_images",	GL_RGB8,	26, 25, 10,	1,	2,	1,	23,	19,	8,	0,	0,	3,	0,	0,	4,	0 },
4239			{ "rgb8_skip_rows",		GL_RGB8,	26, 25, 10,	1,	2,	1,	23,	19,	8,	22,	0,	0,	3,	0,	4,	0 },
4240			{ "rgb8_skip_pixels",	GL_RGB8,	26, 25, 10,	1,	2,	1,	23,	19,	8,	0,	25,	0,	0,	2,	4,	0 }
4241		};
4242
4243		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++)
4244		{
4245			pboGroup->addChild(new TexSubImage2DArrayBufferCase(m_context, (std::string(colorFormats[ndx].name) + "_2d_array").c_str(), "",
4246														   colorFormats[ndx].internalFormat,
4247														   26,	// Width
4248														   25,	// Height
4249														   10,	// Depth
4250														   1,	// Sub X
4251														   2,	// Sub Y
4252														   0,	// Sub Z
4253														   23,	// Sub W
4254														   19,	// Sub H
4255														   8,	// Sub D
4256														   0,	// Image height
4257														   0,	// Row length
4258														   0,	// Skip images
4259														   0,	// Skip rows
4260														   0,	// Skip pixels
4261														   4,	// Alignment
4262														   0	/* offset */));
4263			pboGroup->addChild(new TexSubImage3DBufferCase(m_context, (std::string(colorFormats[ndx].name) + "_3d").c_str(), "",
4264														   colorFormats[ndx].internalFormat,
4265														   26,	// Width
4266														   25,	// Height
4267														   10,	// Depth
4268														   1,	// Sub X
4269														   2,	// Sub Y
4270														   0,	// Sub Z
4271														   23,	// Sub W
4272														   19,	// Sub H
4273														   8,	// Sub D
4274														   0,	// Image height
4275														   0,	// Row length
4276														   0,	// Skip images
4277														   0,	// Skip rows
4278														   0,	// Skip pixels
4279														   4,	// Alignment
4280														   0	/* offset */));
4281		}
4282
4283		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(paramCases); ndx++)
4284		{
4285			pboGroup->addChild(new TexSubImage2DArrayBufferCase(m_context, (std::string(paramCases[ndx].name) + "_2d_array").c_str(), "",
4286														   paramCases[ndx].format,
4287														   paramCases[ndx].width,
4288														   paramCases[ndx].height,
4289														   paramCases[ndx].depth,
4290														   paramCases[ndx].subX,
4291														   paramCases[ndx].subY,
4292														   paramCases[ndx].subZ,
4293														   paramCases[ndx].subW,
4294														   paramCases[ndx].subH,
4295														   paramCases[ndx].subD,
4296														   paramCases[ndx].imageHeight,
4297														   paramCases[ndx].rowLength,
4298														   paramCases[ndx].skipImages,
4299														   paramCases[ndx].skipRows,
4300														   paramCases[ndx].skipPixels,
4301														   paramCases[ndx].alignment,
4302														   paramCases[ndx].offset));
4303			pboGroup->addChild(new TexSubImage3DBufferCase(m_context, (std::string(paramCases[ndx].name) + "_3d").c_str(), "",
4304														   paramCases[ndx].format,
4305														   paramCases[ndx].width,
4306														   paramCases[ndx].height,
4307														   paramCases[ndx].depth,
4308														   paramCases[ndx].subX,
4309														   paramCases[ndx].subY,
4310														   paramCases[ndx].subZ,
4311														   paramCases[ndx].subW,
4312														   paramCases[ndx].subH,
4313														   paramCases[ndx].subD,
4314														   paramCases[ndx].imageHeight,
4315														   paramCases[ndx].rowLength,
4316														   paramCases[ndx].skipImages,
4317														   paramCases[ndx].skipRows,
4318														   paramCases[ndx].skipPixels,
4319														   paramCases[ndx].alignment,
4320														   paramCases[ndx].offset));
4321		}
4322	}
4323
4324	// glTexSubImage3D() depth cases.
4325	{
4326		tcu::TestCaseGroup* shadow3dGroup = new tcu::TestCaseGroup(m_testCtx, "texsubimage3d_depth", "glTexSubImage3D() with depth or depth/stencil format");
4327		addChild(shadow3dGroup);
4328
4329		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilFormats); ndx++)
4330		{
4331			const int	tex2DArrayWidth		= 57;
4332			const int	tex2DArrayHeight	= 44;
4333			const int	tex2DArrayLevels	= 5;
4334
4335			shadow3dGroup->addChild(new TexSubImage2DArrayDepthCase(m_context, (std::string(depthStencilFormats[ndx].name) + "_2d_array").c_str(), "", depthStencilFormats[ndx].internalFormat, tex2DArrayWidth, tex2DArrayHeight, tex2DArrayLevels));
4336		}
4337	}
4338
4339	// glTexStorage2D() cases.
4340	{
4341		tcu::TestCaseGroup* texStorageGroup = new tcu::TestCaseGroup(m_testCtx, "texstorage2d", "Basic glTexStorage2D() usage");
4342		addChild(texStorageGroup);
4343
4344		// All formats.
4345		tcu::TestCaseGroup* formatGroup = new tcu::TestCaseGroup(m_testCtx, "format", "glTexStorage2D() with all formats");
4346		texStorageGroup->addChild(formatGroup);
4347
4348		// Color formats.
4349		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
4350		{
4351			const char*	fmtName			= colorFormats[formatNdx].name;
4352			deUint32	internalFormat	= colorFormats[formatNdx].internalFormat;
4353			const int	tex2DWidth		= 117;
4354			const int	tex2DHeight		= 97;
4355			int			tex2DLevels		= maxLevelCount(tex2DWidth, tex2DHeight);
4356			const int	cubeSize		= 57;
4357			int			cubeLevels		= maxLevelCount(cubeSize, cubeSize);
4358
4359			formatGroup->addChild(new BasicTexStorage2DCase		(m_context, (string(fmtName) + "_2d").c_str(),		"", internalFormat, tex2DWidth, tex2DHeight, tex2DLevels));
4360			formatGroup->addChild(new BasicTexStorageCubeCase	(m_context, (string(fmtName) + "_cube").c_str(),	"", internalFormat, cubeSize, cubeLevels));
4361		}
4362
4363		// Depth / stencil formats.
4364		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); formatNdx++)
4365		{
4366			const char*	fmtName			= depthStencilFormats[formatNdx].name;
4367			deUint32	internalFormat	= depthStencilFormats[formatNdx].internalFormat;
4368			const int	tex2DWidth		= 117;
4369			const int	tex2DHeight		= 97;
4370			int			tex2DLevels		= maxLevelCount(tex2DWidth, tex2DHeight);
4371			const int	cubeSize		= 57;
4372			int			cubeLevels		= maxLevelCount(cubeSize, cubeSize);
4373
4374			formatGroup->addChild(new BasicTexStorage2DCase		(m_context, (string(fmtName) + "_2d").c_str(),		"", internalFormat, tex2DWidth, tex2DHeight, tex2DLevels));
4375			formatGroup->addChild(new BasicTexStorageCubeCase	(m_context, (string(fmtName) + "_cube").c_str(),	"", internalFormat, cubeSize, cubeLevels));
4376		}
4377
4378		// Sizes.
4379		static const struct
4380		{
4381			int				width;
4382			int				height;
4383			int				levels;
4384		} tex2DSizes[] =
4385		{
4386			//	W	H	L
4387			{	1,	1,	1 },
4388			{	2,	2,	2 },
4389			{	64,	32,	7 },
4390			{	32,	64,	4 },
4391			{	57,	63,	1 },
4392			{	57,	63,	2 },
4393			{	57,	63,	6 }
4394		};
4395		static const struct
4396		{
4397			int		size;
4398			int		levels;
4399		} cubeSizes[] =
4400		{
4401			//	S	L
4402			{	1,	1 },
4403			{	2,	2 },
4404			{	57,	1 },
4405			{	57,	2 },
4406			{	57,	6 },
4407			{	64,	4 },
4408			{	64,	7 },
4409		};
4410
4411		tcu::TestCaseGroup* sizeGroup = new tcu::TestCaseGroup(m_testCtx, "size", "glTexStorage2D() with various sizes");
4412		texStorageGroup->addChild(sizeGroup);
4413
4414		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(tex2DSizes); ndx++)
4415		{
4416			const deUint32		format		= GL_RGBA8;
4417			int					width		= tex2DSizes[ndx].width;
4418			int					height		= tex2DSizes[ndx].height;
4419			int					levels		= tex2DSizes[ndx].levels;
4420			string				name		= string("2d_") + de::toString(width) + "x" + de::toString(height) + "_" + de::toString(levels) + "_levels";
4421
4422			sizeGroup->addChild(new BasicTexStorage2DCase(m_context, name.c_str(), "", format, width, height, levels));
4423		}
4424
4425		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cubeSizes); ndx++)
4426		{
4427			const deUint32		format		= GL_RGBA8;
4428			int					size		= cubeSizes[ndx].size;
4429			int					levels		= cubeSizes[ndx].levels;
4430			string				name		= string("cube_") + de::toString(size) + "x" + de::toString(size) + "_" + de::toString(levels) + "_levels";
4431
4432			sizeGroup->addChild(new BasicTexStorageCubeCase(m_context, name.c_str(), "", format, size, levels));
4433		}
4434	}
4435
4436	// glTexStorage3D() cases.
4437	{
4438		tcu::TestCaseGroup* texStorageGroup = new tcu::TestCaseGroup(m_testCtx, "texstorage3d", "Basic glTexStorage3D() usage");
4439		addChild(texStorageGroup);
4440
4441		// All formats.
4442		tcu::TestCaseGroup* formatGroup = new tcu::TestCaseGroup(m_testCtx, "format", "glTexStorage3D() with all formats");
4443		texStorageGroup->addChild(formatGroup);
4444
4445		// Color formats.
4446		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(colorFormats); formatNdx++)
4447		{
4448			const char*	fmtName				= colorFormats[formatNdx].name;
4449			deUint32	internalFormat		= colorFormats[formatNdx].internalFormat;
4450			const int	tex2DArrayWidth		= 57;
4451			const int	tex2DArrayHeight	= 13;
4452			const int	tex2DArrayLayers	= 7;
4453			int			tex2DArrayLevels	= maxLevelCount(tex2DArrayWidth, tex2DArrayHeight);
4454			const int	tex3DWidth			= 59;
4455			const int	tex3DHeight			= 37;
4456			const int	tex3DDepth			= 11;
4457			int			tex3DLevels			= maxLevelCount(tex3DWidth, tex3DHeight, tex3DDepth);
4458
4459			formatGroup->addChild(new BasicTexStorage2DArrayCase	(m_context, (string(fmtName) + "_2d_array").c_str(),	"", internalFormat, tex2DArrayWidth, tex2DArrayHeight, tex2DArrayLayers, tex2DArrayLevels));
4460			formatGroup->addChild(new BasicTexStorage3DCase			(m_context, (string(fmtName) + "_3d").c_str(),			"", internalFormat, tex3DWidth, tex3DHeight, tex3DDepth, tex3DLevels));
4461		}
4462
4463		// Depth/stencil formats (only 2D texture array is supported).
4464		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); formatNdx++)
4465		{
4466			const char*	fmtName				= depthStencilFormats[formatNdx].name;
4467			deUint32	internalFormat		= depthStencilFormats[formatNdx].internalFormat;
4468			const int	tex2DArrayWidth		= 57;
4469			const int	tex2DArrayHeight	= 13;
4470			const int	tex2DArrayLayers	= 7;
4471			int			tex2DArrayLevels	= maxLevelCount(tex2DArrayWidth, tex2DArrayHeight);
4472
4473			formatGroup->addChild(new BasicTexStorage2DArrayCase	(m_context, (string(fmtName) + "_2d_array").c_str(),	"", internalFormat, tex2DArrayWidth, tex2DArrayHeight, tex2DArrayLayers, tex2DArrayLevels));
4474		}
4475
4476		// Sizes.
4477		static const struct
4478		{
4479			int				width;
4480			int				height;
4481			int				layers;
4482			int				levels;
4483		} tex2DArraySizes[] =
4484		{
4485			//	W	H	La	Le
4486			{	1,	1,	1,	1 },
4487			{	2,	2,	2,	2 },
4488			{	64,	32,	3,	7 },
4489			{	32,	64,	3,	4 },
4490			{	57,	63,	5,	1 },
4491			{	57,	63,	5,	2 },
4492			{	57,	63,	5,	6 }
4493		};
4494		static const struct
4495		{
4496			int				width;
4497			int				height;
4498			int				depth;
4499			int				levels;
4500		} tex3DSizes[] =
4501		{
4502			//	W	H	D	L
4503			{	1,	1,	1,	1 },
4504			{	2,	2,	2,	2 },
4505			{	64,	32,	16,	7 },
4506			{	32,	64,	16,	4 },
4507			{	32,	16,	64,	4 },
4508			{	57,	63,	11,	1 },
4509			{	57,	63,	11,	2 },
4510			{	57,	63,	11,	6 }
4511		};
4512
4513		tcu::TestCaseGroup* sizeGroup = new tcu::TestCaseGroup(m_testCtx, "size", "glTexStorage2D() with various sizes");
4514		texStorageGroup->addChild(sizeGroup);
4515
4516		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(tex2DArraySizes); ndx++)
4517		{
4518			const deUint32		format		= GL_RGBA8;
4519			int					width		= tex2DArraySizes[ndx].width;
4520			int					height		= tex2DArraySizes[ndx].height;
4521			int					layers		= tex2DArraySizes[ndx].layers;
4522			int					levels		= tex2DArraySizes[ndx].levels;
4523			string				name		= string("2d_array_") + de::toString(width) + "x" + de::toString(height) + "x" + de::toString(layers) + "_" + de::toString(levels) + "_levels";
4524
4525			sizeGroup->addChild(new BasicTexStorage2DArrayCase(m_context, name.c_str(), "", format, width, height, layers, levels));
4526		}
4527
4528		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(tex3DSizes); ndx++)
4529		{
4530			const deUint32		format		= GL_RGBA8;
4531			int					width		= tex3DSizes[ndx].width;
4532			int					height		= tex3DSizes[ndx].height;
4533			int					depth		= tex3DSizes[ndx].depth;
4534			int					levels		= tex3DSizes[ndx].levels;
4535			string				name		= string("3d_") + de::toString(width) + "x" + de::toString(height) + "x" + de::toString(depth) + "_" + de::toString(levels) + "_levels";
4536
4537			sizeGroup->addChild(new BasicTexStorage3DCase(m_context, name.c_str(), "", format, width, height, depth, levels));
4538		}
4539	}
4540}
4541
4542} // Functional
4543} // gles3
4544} // deqp
4545