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