1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.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 "es2fTextureSpecificationTests.hpp"
30#include "tcuTestLog.hpp"
31#include "tcuImageCompare.hpp"
32#include "gluTextureUtil.hpp"
33#include "sglrContextUtil.hpp"
34#include "sglrContextWrapper.hpp"
35#include "sglrGLContext.hpp"
36#include "sglrReferenceContext.hpp"
37#include "glsTextureTestUtil.hpp"
38#include "tcuTextureUtil.hpp"
39#include "tcuFormatUtil.hpp"
40#include "tcuVectorUtil.hpp"
41#include "deRandom.hpp"
42#include "deStringUtil.hpp"
43
44#include "glwEnums.hpp"
45#include "glwFunctions.hpp"
46
47namespace deqp
48{
49namespace gles2
50{
51namespace Functional
52{
53
54using std::string;
55using std::vector;
56using std::pair;
57using tcu::TestLog;
58using tcu::Vec4;
59using tcu::IVec4;
60using tcu::UVec4;
61
62tcu::TextureFormat mapGLUnsizedInternalFormat (deUint32 internalFormat)
63{
64	using tcu::TextureFormat;
65	switch (internalFormat)
66	{
67		case GL_ALPHA:				return TextureFormat(TextureFormat::A,		TextureFormat::UNORM_INT8);
68		case GL_LUMINANCE:			return TextureFormat(TextureFormat::L,		TextureFormat::UNORM_INT8);
69		case GL_LUMINANCE_ALPHA:	return TextureFormat(TextureFormat::LA,		TextureFormat::UNORM_INT8);
70		case GL_RGB:				return TextureFormat(TextureFormat::RGB,	TextureFormat::UNORM_INT8);
71		case GL_RGBA:				return TextureFormat(TextureFormat::RGBA,	TextureFormat::UNORM_INT8);
72		default:
73			throw tcu::InternalError(string("Can't map GL unsized internal format (") + tcu::toHex(internalFormat).toString() + ") to texture format");
74	}
75}
76
77template <int Size>
78static tcu::Vector<float, Size> randomVector (de::Random& rnd, const tcu::Vector<float, Size>& minVal = tcu::Vector<float, Size>(0.0f), const tcu::Vector<float, Size>& maxVal = tcu::Vector<float, Size>(1.0f))
79{
80	tcu::Vector<float, Size> res;
81	for (int ndx = 0; ndx < Size; ndx++)
82		res[ndx] = rnd.getFloat(minVal[ndx], maxVal[ndx]);
83	return res;
84}
85
86static tcu::IVec4 getPixelFormatCompareDepth (const tcu::PixelFormat& pixelFormat, tcu::TextureFormat textureFormat)
87{
88	switch (textureFormat.order)
89	{
90		case tcu::TextureFormat::L:
91		case tcu::TextureFormat::LA:
92			return tcu::IVec4(pixelFormat.redBits, pixelFormat.redBits, pixelFormat.redBits, pixelFormat.alphaBits);
93		default:
94			return tcu::IVec4(pixelFormat.redBits, pixelFormat.greenBits, pixelFormat.blueBits, pixelFormat.alphaBits);
95	}
96}
97
98static tcu::UVec4 computeCompareThreshold (const tcu::PixelFormat& pixelFormat, tcu::TextureFormat textureFormat)
99{
100	const IVec4		texFormatBits		= tcu::getTextureFormatBitDepth(textureFormat);
101	const IVec4		pixelFormatBits		= getPixelFormatCompareDepth(pixelFormat, textureFormat);
102	const IVec4		accurateFmtBits		= min(pixelFormatBits, texFormatBits);
103	const IVec4		compareBits			= select(accurateFmtBits, IVec4(8), greaterThan(accurateFmtBits, IVec4(0))) - 1;
104
105	return (IVec4(1) << (8-compareBits)).asUint();
106}
107
108class GradientShader : public sglr::ShaderProgram
109{
110public:
111	GradientShader (void)
112		: ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
113					<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
114					<< sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
115					<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
116					<< sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
117					<< sglr::pdec::VertexSource("attribute highp vec4 a_position;\n"
118												"attribute mediump vec2 a_coord;\n"
119												"varying mediump vec2 v_coord;\n"
120												"void main (void)\n"
121												"{\n"
122												"	gl_Position = a_position;\n"
123												"	v_coord = a_coord;\n"
124												"}\n")
125					<< sglr::pdec::FragmentSource("varying mediump vec2 v_coord;\n"
126												  "void main (void)\n"
127												  "{\n"
128												  "	mediump float x = v_coord.x;\n"
129												  "	mediump float y = v_coord.y;\n"
130												  "	mediump float f0 = (x + y) * 0.5;\n"
131												  "	mediump float f1 = 0.5 + (x - y) * 0.5;\n"
132												  "	gl_FragColor = vec4(f0, f1, 1.0-f0, 1.0-f1);\n"
133												  "}\n"))
134	{
135	}
136
137	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
138	{
139		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
140		{
141			rr::VertexPacket& packet = *packets[packetNdx];
142
143			packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
144			packet.outputs[0]	= rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
145		}
146	}
147
148	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
149	{
150		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
151		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
152		{
153			const tcu::Vec4		coord	= rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
154			const float			x		= coord.x();
155			const float			y		= coord.y();
156			const float			f0		= (x + y) * 0.5f;
157			const float			f1		= 0.5f + (x - y) * 0.5f;
158
159			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, tcu::Vec4(f0, f1, 1.0f-f0, 1.0f-f1));
160		}
161	}
162};
163
164class Tex2DShader : public sglr::ShaderProgram
165{
166public:
167	Tex2DShader (void)
168		: ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
169					<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
170					<< sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
171					<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
172					<< sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
173					<< sglr::pdec::Uniform("u_sampler0", glu::TYPE_SAMPLER_2D)
174					<< sglr::pdec::VertexSource("attribute highp vec4 a_position;\n"
175												"attribute mediump vec2 a_coord;\n"
176												"varying mediump vec2 v_coord;\n"
177												"void main (void)\n"
178												"{\n"
179												"	gl_Position = a_position;\n"
180												"	v_coord = a_coord;\n"
181												"}\n")
182					<< sglr::pdec::FragmentSource("uniform sampler2D u_sampler0;\n"
183												  "varying mediump vec2 v_coord;\n"
184												  "void main (void)\n"
185												  "{\n"
186												  "	gl_FragColor = texture2D(u_sampler0, v_coord);\n"
187												  "}\n"))
188	{
189	}
190
191	void setUniforms (sglr::Context& ctx, deUint32 program) const
192	{
193		ctx.useProgram(program);
194		ctx.uniform1i(ctx.getUniformLocation(program, "u_sampler0"), 0);
195	}
196
197	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
198	{
199		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
200		{
201			rr::VertexPacket& packet = *packets[packetNdx];
202
203			packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
204			packet.outputs[0]	= rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
205		}
206	}
207
208	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
209	{
210		tcu::Vec2 texCoords[4];
211		tcu::Vec4 colors[4];
212
213		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
214		{
215			// setup tex coords
216			for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
217			{
218				const tcu::Vec4	coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
219				texCoords[fragNdx] = tcu::Vec2(coord.x(), coord.y());
220			}
221
222			// Sample
223			m_uniforms[0].sampler.tex2D->sample4(colors, texCoords);
224
225			// Write out
226			for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
227				rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, colors[fragNdx]);
228		}
229	}
230};
231
232static const char* s_cubeSwizzles[] =
233{
234	"vec3(-1, -y, +x)",
235	"vec3(+1, -y, -x)",
236	"vec3(+x, -1, -y)",
237	"vec3(+x, +1, +y)",
238	"vec3(-x, -y, -1)",
239	"vec3(+x, -y, +1)"
240};
241
242class TexCubeShader : public sglr::ShaderProgram
243{
244public:
245	TexCubeShader (tcu::CubeFace face)
246		: ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
247					<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
248					<< sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
249					<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
250					<< sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
251					<< sglr::pdec::Uniform("u_sampler0", glu::TYPE_SAMPLER_CUBE)
252					<< sglr::pdec::VertexSource("attribute highp vec4 a_position;\n"
253												"attribute mediump vec2 a_coord;\n"
254												"varying mediump vec2 v_coord;\n"
255												"void main (void)\n"
256												"{\n"
257												"	gl_Position = a_position;\n"
258												"	v_coord = a_coord;\n"
259												"}\n")
260					<< sglr::pdec::FragmentSource(string("") +
261												  "uniform samplerCube u_sampler0;\n"
262												  "varying mediump vec2 v_coord;\n"
263												  "void main (void)\n"
264												  "{\n"
265												  "	mediump float x = v_coord.x*2.0 - 1.0;\n"
266												  "	mediump float y = v_coord.y*2.0 - 1.0;\n"
267												  "	gl_FragColor = textureCube(u_sampler0, " + s_cubeSwizzles[face] + ");\n"
268												  "}\n"))
269		, m_face(face)
270	{
271	}
272
273	void setUniforms (sglr::Context& ctx, deUint32 program) const
274	{
275		ctx.useProgram(program);
276		ctx.uniform1i(ctx.getUniformLocation(program, "u_sampler0"), 0);
277	}
278
279	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
280	{
281		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
282		{
283			rr::VertexPacket& packet = *packets[packetNdx];
284
285			packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
286			packet.outputs[0]	= rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
287		}
288	}
289
290	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
291	{
292		tcu::Vec3 texCoords[4];
293		tcu::Vec4 colors[4];
294
295		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
296		{
297			// setup tex coords
298			for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
299			{
300				const tcu::Vec4	coord	= rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
301				const float		x		= coord.x()*2.0f - 1.0f;
302				const float		y		= coord.y()*2.0f - 1.0f;
303
304				// Swizzle tex coords
305				switch (m_face)
306				{
307					case tcu::CUBEFACE_NEGATIVE_X:	texCoords[fragNdx] = tcu::Vec3(-1.0f,    -y,    +x);		break;
308					case tcu::CUBEFACE_POSITIVE_X:	texCoords[fragNdx] = tcu::Vec3(+1.0f,    -y,    -x);		break;
309					case tcu::CUBEFACE_NEGATIVE_Y:	texCoords[fragNdx] = tcu::Vec3(   +x, -1.0f,    -y);		break;
310					case tcu::CUBEFACE_POSITIVE_Y:	texCoords[fragNdx] = tcu::Vec3(   +x, +1.0f,    +y);		break;
311					case tcu::CUBEFACE_NEGATIVE_Z:	texCoords[fragNdx] = tcu::Vec3(   -x,    -y, -1.0f);		break;
312					case tcu::CUBEFACE_POSITIVE_Z:	texCoords[fragNdx] = tcu::Vec3(   +x,    -y, +1.0f);		break;
313					default:
314						DE_ASSERT(false);
315				}
316			}
317
318			// Sample
319			m_uniforms[0].sampler.texCube->sample4(colors, texCoords);
320
321			// Write out
322			for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
323				rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, colors[fragNdx]);
324		}
325	}
326private:
327	tcu::CubeFace m_face;
328};
329
330enum TextureType
331{
332	TEXTURETYPE_2D = 0,
333	TEXTURETYPE_CUBE,
334
335	TEXTURETYPE_LAST
336};
337
338enum Flags
339{
340	MIPMAPS		= (1<<0)
341};
342
343static const deUint32 s_cubeMapFaces[] =
344{
345	GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
346	GL_TEXTURE_CUBE_MAP_POSITIVE_X,
347	GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
348	GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
349	GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
350	GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
351};
352
353class TextureSpecCase : public TestCase, public sglr::ContextWrapper
354{
355public:
356								TextureSpecCase		(Context& context, const char* name, const char* desc, const TextureType type, const tcu::TextureFormat format, const deUint32 flags, int width, int height);
357								~TextureSpecCase	(void);
358
359	IterateResult				iterate				(void);
360
361protected:
362	virtual void				createTexture		(void) = DE_NULL;
363
364	const TextureType			m_texType;
365	const tcu::TextureFormat	m_texFormat;
366	const deUint32				m_flags;
367	const int					m_width;
368	const int					m_height;
369
370private:
371								TextureSpecCase		(const TextureSpecCase& other);
372	TextureSpecCase&			operator=			(const TextureSpecCase& other);
373
374	void						verifyTex2D			(sglr::GLContext& gles2Context, sglr::ReferenceContext& refContext);
375	void						verifyTexCube		(sglr::GLContext& gles2Context, sglr::ReferenceContext& refContext);
376
377	void						renderTex2D			(tcu::Surface& dst, int width, int height);
378	void						renderTexCube		(tcu::Surface& dst, int width, int height, tcu::CubeFace face);
379
380	void						readPixels			(tcu::Surface& dst, int x, int y, int width, int height);
381
382	// \todo [2012-03-27 pyry] Renderer should be extended to allow custom attributes, that would clean up this cubemap mess.
383	Tex2DShader					m_tex2DShader;
384	TexCubeShader				m_texCubeNegXShader;
385	TexCubeShader				m_texCubePosXShader;
386	TexCubeShader				m_texCubeNegYShader;
387	TexCubeShader				m_texCubePosYShader;
388	TexCubeShader				m_texCubeNegZShader;
389	TexCubeShader				m_texCubePosZShader;
390};
391
392TextureSpecCase::TextureSpecCase (Context& context, const char* name, const char* desc, const TextureType type, const tcu::TextureFormat format, const deUint32 flags, int width, int height)
393	: TestCase				(context, name, desc)
394	, m_texType				(type)
395	, m_texFormat			(format)
396	, m_flags				(flags)
397	, m_width				(width)
398	, m_height				(height)
399	, m_texCubeNegXShader	(tcu::CUBEFACE_NEGATIVE_X)
400	, m_texCubePosXShader	(tcu::CUBEFACE_POSITIVE_X)
401	, m_texCubeNegYShader	(tcu::CUBEFACE_NEGATIVE_Y)
402	, m_texCubePosYShader	(tcu::CUBEFACE_POSITIVE_Y)
403	, m_texCubeNegZShader	(tcu::CUBEFACE_NEGATIVE_Z)
404	, m_texCubePosZShader	(tcu::CUBEFACE_POSITIVE_Z)
405{
406}
407
408TextureSpecCase::~TextureSpecCase (void)
409{
410}
411
412TextureSpecCase::IterateResult TextureSpecCase::iterate (void)
413{
414	glu::RenderContext&			renderCtx				= TestCase::m_context.getRenderContext();
415	const tcu::RenderTarget&	renderTarget			= renderCtx.getRenderTarget();
416	tcu::TestLog&				log						= m_testCtx.getLog();
417
418	DE_ASSERT(m_width <= 256 && m_height <= 256);
419	if (renderTarget.getWidth() < m_width || renderTarget.getHeight() < m_height)
420		throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
421
422	// Context size, and viewport for GLES2
423	de::Random		rnd			(deStringHash(getName()));
424	int				width		= deMin32(renderTarget.getWidth(),	256);
425	int				height		= deMin32(renderTarget.getHeight(),	256);
426	int				x			= rnd.getInt(0, renderTarget.getWidth()		- width);
427	int				y			= rnd.getInt(0, renderTarget.getHeight()	- height);
428
429	// Contexts.
430	sglr::GLContext					gles2Context	(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height));
431	sglr::ReferenceContextBuffers	refBuffers		(tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), 0 /* depth */, 0 /* stencil */, width, height);
432	sglr::ReferenceContext			refContext		(sglr::ReferenceContextLimits(renderCtx), refBuffers.getColorbuffer(), refBuffers.getDepthbuffer(), refBuffers.getStencilbuffer());
433
434	// Clear color buffer.
435	for (int ndx = 0; ndx < 2; ndx++)
436	{
437		setContext(ndx ? (sglr::Context*)&refContext : (sglr::Context*)&gles2Context);
438		glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
439		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
440	}
441
442	// Construct texture using both GLES2 and reference contexts.
443	for (int ndx = 0; ndx < 2; ndx++)
444	{
445		setContext(ndx ? (sglr::Context*)&refContext : (sglr::Context*)&gles2Context);
446		createTexture();
447		TCU_CHECK(glGetError() == GL_NO_ERROR);
448	}
449
450	// Setup texture filtering state.
451	for (int ndx = 0; ndx < 2; ndx++)
452	{
453		setContext(ndx ? (sglr::Context*)&refContext : (sglr::Context*)&gles2Context);
454
455		deUint32 texTarget = m_texType == TEXTURETYPE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP;
456		glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER,	(m_flags & MIPMAPS) ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST);
457		glTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
458		glTexParameteri(texTarget, GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
459		glTexParameteri(texTarget, GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
460	}
461
462	// Initialize case result to pass.
463	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
464
465	// Disable logging.
466	gles2Context.enableLogging(0);
467
468	// Verify results.
469	switch (m_texType)
470	{
471		case TEXTURETYPE_2D:	verifyTex2D		(gles2Context, refContext);	break;
472		case TEXTURETYPE_CUBE:	verifyTexCube	(gles2Context, refContext);	break;
473		default:
474			DE_ASSERT(false);
475	}
476
477	return STOP;
478}
479
480void TextureSpecCase::verifyTex2D (sglr::GLContext& gles2Context, sglr::ReferenceContext& refContext)
481{
482	int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1;
483
484	DE_ASSERT(m_texType == TEXTURETYPE_2D);
485
486	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
487	{
488		int				levelW		= de::max(1, m_width >> levelNdx);
489		int				levelH		= de::max(1, m_height >> levelNdx);
490		tcu::Surface	reference;
491		tcu::Surface	result;
492
493		if (levelW <= 2 || levelH <= 2)
494			continue; // Don't bother checking.
495
496		// Render with GLES2
497		setContext(&gles2Context);
498		renderTex2D(result, levelW, levelH);
499
500		// Render reference.
501		setContext(&refContext);
502		renderTex2D(reference, levelW, levelH);
503
504		{
505			tcu::UVec4	threshold	= computeCompareThreshold(m_context.getRenderTarget().getPixelFormat(), m_texFormat);
506			bool		isOk		= tcu::intThresholdCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(), result.getAccess(), threshold,
507															   levelNdx == 0 ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
508
509			if (!isOk)
510			{
511				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
512				break;
513			}
514		}
515	}
516}
517
518void TextureSpecCase::verifyTexCube (sglr::GLContext& gles2Context, sglr::ReferenceContext& refContext)
519{
520	int numLevels = (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1;
521
522	DE_ASSERT(m_texType == TEXTURETYPE_CUBE);
523
524	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
525	{
526		int		levelW	= de::max(1, m_width >> levelNdx);
527		int		levelH	= de::max(1, m_height >> levelNdx);
528		bool	isOk	= true;
529
530		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
531		{
532			tcu::Surface	reference;
533			tcu::Surface	result;
534
535			if (levelW <= 2 || levelH <= 2)
536				continue; // Don't bother checking.
537
538			// Render with GLES2
539			setContext(&gles2Context);
540			renderTexCube(result, levelW, levelH, (tcu::CubeFace)face);
541
542			// Render reference.
543			setContext(&refContext);
544			renderTexCube(reference, levelW, levelH, (tcu::CubeFace)face);
545
546			const float	threshold	= 0.02f;
547			isOk = tcu::fuzzyCompare(m_testCtx.getLog(), "Result", (string("Image comparison result: ") + de::toString((tcu::CubeFace)face)).c_str(), reference, result, threshold,
548									 levelNdx == 0 ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
549
550			if (!isOk)
551			{
552				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
553				break;
554			}
555		}
556
557		if (!isOk)
558			break;
559	}
560}
561
562void TextureSpecCase::renderTex2D (tcu::Surface& dst, int width, int height)
563{
564	int			targetW		= getWidth();
565	int			targetH		= getHeight();
566
567	float		w			= (float)width	/ (float)targetW;
568	float		h			= (float)height	/ (float)targetH;
569
570	deUint32	shaderID	= getCurrentContext()->createProgram(&m_tex2DShader);
571
572	m_tex2DShader.setUniforms(*getCurrentContext(), shaderID);
573	sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(-1.0f + w*2.0f, -1.0f + h*2.0f, 0.0f));
574
575	// Read pixels back.
576	readPixels(dst, 0, 0, width, height);
577}
578
579void TextureSpecCase::renderTexCube (tcu::Surface& dst, int width, int height, tcu::CubeFace face)
580{
581	int		targetW		= getWidth();
582	int		targetH		= getHeight();
583
584	float	w			= (float)width	/ (float)targetW;
585	float	h			= (float)height	/ (float)targetH;
586
587	TexCubeShader* shaders[] =
588	{
589		&m_texCubeNegXShader,
590		&m_texCubePosXShader,
591		&m_texCubeNegYShader,
592		&m_texCubePosYShader,
593		&m_texCubeNegZShader,
594		&m_texCubePosZShader
595	};
596
597	deUint32	shaderID	= getCurrentContext()->createProgram(shaders[face]);
598
599	shaders[face]->setUniforms(*getCurrentContext(), shaderID);
600	sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(-1.0f + w*2.0f, -1.0f + h*2.0f, 0.0f));
601
602	// Read pixels back.
603	readPixels(dst, 0, 0, width, height);
604}
605
606void TextureSpecCase::readPixels (tcu::Surface& dst, int x, int y, int width, int height)
607{
608	dst.setSize(width, height);
609	glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, dst.getAccess().getDataPtr());
610}
611
612// Basic TexImage2D() with 2D texture usage
613class BasicTexImage2DCase : public TextureSpecCase
614{
615public:
616	BasicTexImage2DCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height)
617		: TextureSpecCase	(context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width, height)
618		, m_format			(format)
619		, m_dataType		(dataType)
620	{
621	}
622
623protected:
624	void createTexture (void)
625	{
626		tcu::TextureFormat	fmt			= m_texFormat;
627		int					numLevels	= (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1;
628		deUint32			tex			= 0;
629		tcu::TextureLevel	levelData	(fmt);
630		de::Random			rnd			(deStringHash(getName()));
631
632		glGenTextures(1, &tex);
633		glBindTexture(GL_TEXTURE_2D, tex);
634		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
635
636		for (int ndx = 0; ndx < numLevels; ndx++)
637		{
638			int		levelW		= de::max(1, m_width >> ndx);
639			int		levelH		= de::max(1, m_height >> ndx);
640			Vec4	gMin		= randomVector<4>(rnd);
641			Vec4	gMax		= randomVector<4>(rnd);
642
643			levelData.setSize(levelW, levelH);
644			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
645
646			glTexImage2D(GL_TEXTURE_2D, ndx, m_format, levelW, levelH, 0, m_format, m_dataType, levelData.getAccess().getDataPtr());
647		}
648	}
649
650	deUint32	m_format;
651	deUint32	m_dataType;
652};
653
654// Basic TexImage2D() with cubemap usage
655class BasicTexImageCubeCase : public TextureSpecCase
656{
657public:
658	BasicTexImageCubeCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height)
659		: TextureSpecCase	(context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags, width, height)
660		, m_format			(format)
661		, m_dataType		(dataType)
662	{
663	}
664
665protected:
666	void createTexture (void)
667	{
668		tcu::TextureFormat	fmt			= m_texFormat;
669		int					numLevels	= (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1;
670		deUint32			tex			= 0;
671		tcu::TextureLevel	levelData	(fmt);
672		de::Random			rnd			(deStringHash(getName()));
673
674		DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2.
675
676		glGenTextures(1, &tex);
677		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
678		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
679
680		for (int ndx = 0; ndx < numLevels; ndx++)
681		{
682			int		levelW		= de::max(1, m_width >> ndx);
683			int		levelH		= de::max(1, m_height >> ndx);
684
685			levelData.setSize(levelW, levelH);
686
687			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
688			{
689				Vec4 gMin = randomVector<4>(rnd);
690				Vec4 gMax = randomVector<4>(rnd);
691
692				tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
693
694				glTexImage2D(s_cubeMapFaces[face], ndx, m_format, levelW, levelH, 0, m_format, m_dataType, levelData.getAccess().getDataPtr());
695			}
696		}
697	}
698
699	deUint32	m_format;
700	deUint32	m_dataType;
701};
702
703// Randomized 2D texture specification using TexImage2D
704class RandomOrderTexImage2DCase : public TextureSpecCase
705{
706public:
707	RandomOrderTexImage2DCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height)
708		: TextureSpecCase	(context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width, height)
709		, m_format			(format)
710		, m_dataType		(dataType)
711	{
712	}
713
714protected:
715	void createTexture (void)
716	{
717		tcu::TextureFormat	fmt			= m_texFormat;
718		int					numLevels	= (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1;
719		deUint32			tex			= 0;
720		tcu::TextureLevel	levelData	(fmt);
721		de::Random			rnd			(deStringHash(getName()));
722
723		glGenTextures(1, &tex);
724		glBindTexture(GL_TEXTURE_2D, tex);
725		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
726
727		vector<int>			levels		(numLevels);
728
729		for (int i = 0; i < numLevels; i++)
730			levels[i] = i;
731		rnd.shuffle(levels.begin(), levels.end());
732
733		for (int ndx = 0; ndx < numLevels; ndx++)
734		{
735			int		levelNdx	= levels[ndx];
736			int		levelW		= de::max(1, m_width	>> levelNdx);
737			int		levelH		= de::max(1, m_height	>> levelNdx);
738			Vec4	gMin		= randomVector<4>(rnd);
739			Vec4	gMax		= randomVector<4>(rnd);
740
741			levelData.setSize(levelW, levelH);
742			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
743
744			glTexImage2D(GL_TEXTURE_2D, levelNdx, m_format, levelW, levelH, 0, m_format, m_dataType, levelData.getAccess().getDataPtr());
745		}
746	}
747
748	deUint32	m_format;
749	deUint32	m_dataType;
750};
751
752// Randomized cubemap texture specification using TexImage2D
753class RandomOrderTexImageCubeCase : public TextureSpecCase
754{
755public:
756	RandomOrderTexImageCubeCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height)
757		: TextureSpecCase	(context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags, width, height)
758		, m_format			(format)
759		, m_dataType		(dataType)
760	{
761	}
762
763protected:
764	void createTexture (void)
765	{
766		tcu::TextureFormat	fmt			= m_texFormat;
767		int					numLevels	= (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1;
768		deUint32			tex			= 0;
769		tcu::TextureLevel	levelData	(fmt);
770		de::Random			rnd			(deStringHash(getName()));
771
772		DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2.
773
774		glGenTextures(1, &tex);
775		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
776		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
777
778		// Level-face pairs.
779		vector<pair<int, tcu::CubeFace> >	images	(numLevels*6);
780
781		for (int ndx = 0; ndx < numLevels; ndx++)
782			for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
783				images[ndx*6 + face] = std::make_pair(ndx, (tcu::CubeFace)face);
784
785		rnd.shuffle(images.begin(), images.end());
786
787		for (int ndx = 0; ndx < (int)images.size(); ndx++)
788		{
789			int				levelNdx	= images[ndx].first;
790			tcu::CubeFace	face		= images[ndx].second;
791			int				levelW		= de::max(1, m_width >> levelNdx);
792			int				levelH		= de::max(1, m_height >> levelNdx);
793			Vec4			gMin		= randomVector<4>(rnd);
794			Vec4			gMax		= randomVector<4>(rnd);
795
796			levelData.setSize(levelW, levelH);
797			tcu::fillWithComponentGradients(levelData.getAccess(), gMin, gMax);
798
799			glTexImage2D(s_cubeMapFaces[face], levelNdx, m_format, levelW, levelH, 0, m_format, m_dataType, levelData.getAccess().getDataPtr());
800		}
801	}
802
803	deUint32	m_format;
804	deUint32	m_dataType;
805};
806
807static inline int getRowPitch (const tcu::TextureFormat& transferFmt, int rowLen, int alignment)
808{
809	int basePitch = transferFmt.getPixelSize()*rowLen;
810	return alignment*(basePitch/alignment + ((basePitch % alignment) ? 1 : 0));
811}
812
813// TexImage2D() unpack alignment case.
814class TexImage2DAlignCase : public TextureSpecCase
815{
816public:
817	TexImage2DAlignCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height, int alignment)
818		: TextureSpecCase	(context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width, height)
819		, m_format			(format)
820		, m_dataType		(dataType)
821		, m_alignment		(alignment)
822	{
823	}
824
825protected:
826	void createTexture (void)
827	{
828		tcu::TextureFormat	fmt			= m_texFormat;
829		int					numLevels	= (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1;
830		deUint32			tex			= 0;
831		vector<deUint8>		data;
832
833		glGenTextures(1, &tex);
834		glBindTexture(GL_TEXTURE_2D, tex);
835		glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
836
837		for (int ndx = 0; ndx < numLevels; ndx++)
838		{
839			int		levelW		= de::max(1, m_width >> ndx);
840			int		levelH		= de::max(1, m_height >> ndx);
841			Vec4	colorA		(1.0f, 0.0f, 0.0f, 1.0f);
842			Vec4	colorB		(0.0f, 1.0f, 0.0f, 1.0f);
843			int		rowPitch	= getRowPitch(fmt, levelW, m_alignment);
844			int		cellSize	= de::max(1, de::min(levelW >> 2, levelH >> 2));
845
846			data.resize(rowPitch*levelH);
847			tcu::fillWithGrid(tcu::PixelBufferAccess(fmt, levelW, levelH, 1, rowPitch, 0, &data[0]), cellSize, colorA, colorB);
848
849			glTexImage2D(GL_TEXTURE_2D, ndx, m_format, levelW, levelH, 0, m_format, m_dataType, &data[0]);
850		}
851	}
852
853	deUint32	m_format;
854	deUint32	m_dataType;
855	int			m_alignment;
856};
857
858// TexImage2D() unpack alignment case.
859class TexImageCubeAlignCase : public TextureSpecCase
860{
861public:
862	TexImageCubeAlignCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height, int alignment)
863		: TextureSpecCase	(context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags, width, height)
864		, m_format			(format)
865		, m_dataType		(dataType)
866		, m_alignment		(alignment)
867	{
868	}
869
870protected:
871	void createTexture (void)
872	{
873		tcu::TextureFormat	fmt			= m_texFormat;
874		int					numLevels	= (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1;
875		deUint32			tex			= 0;
876		vector<deUint8>		data;
877
878		DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2.
879
880		glGenTextures(1, &tex);
881		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
882		glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
883
884		for (int ndx = 0; ndx < numLevels; ndx++)
885		{
886			int		levelW		= de::max(1, m_width >> ndx);
887			int		levelH		= de::max(1, m_height >> ndx);
888			int		rowPitch	= getRowPitch(fmt, levelW, m_alignment);
889			Vec4	colorA		(1.0f, 0.0f, 0.0f, 1.0f);
890			Vec4	colorB		(0.0f, 1.0f, 0.0f, 1.0f);
891			int		cellSize	= de::max(1, de::min(levelW >> 2, levelH >> 2));
892
893			data.resize(rowPitch*levelH);
894			tcu::fillWithGrid(tcu::PixelBufferAccess(fmt, levelW, levelH, 1, rowPitch, 0, &data[0]), cellSize, colorA, colorB);
895
896			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
897				glTexImage2D(s_cubeMapFaces[face], ndx, m_format, levelW, levelH, 0, m_format, m_dataType, &data[0]);
898		}
899	}
900
901	deUint32	m_format;
902	deUint32	m_dataType;
903	int			m_alignment;
904};
905
906// Basic TexSubImage2D() with 2D texture usage
907class BasicTexSubImage2DCase : public TextureSpecCase
908{
909public:
910	BasicTexSubImage2DCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height)
911		: TextureSpecCase	(context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width, height)
912		, m_format			(format)
913		, m_dataType		(dataType)
914	{
915	}
916
917protected:
918	void createTexture (void)
919	{
920		tcu::TextureFormat	fmt			= m_texFormat;
921		int					numLevels	= (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1;
922		deUint32			tex			= 0;
923		tcu::TextureLevel	data		(fmt);
924		de::Random			rnd			(deStringHash(getName()));
925
926		glGenTextures(1, &tex);
927		glBindTexture(GL_TEXTURE_2D, tex);
928		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
929
930		// First specify full texture.
931		for (int ndx = 0; ndx < numLevels; ndx++)
932		{
933			int		levelW		= de::max(1, m_width >> ndx);
934			int		levelH		= de::max(1, m_height >> ndx);
935			Vec4	gMin		= randomVector<4>(rnd);
936			Vec4	gMax		= randomVector<4>(rnd);
937
938			data.setSize(levelW, levelH);
939			tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
940
941			glTexImage2D(GL_TEXTURE_2D, ndx, m_format, levelW, levelH, 0, m_format, m_dataType, data.getAccess().getDataPtr());
942		}
943
944		// Re-specify parts of each level.
945		for (int ndx = 0; ndx < numLevels; ndx++)
946		{
947			int		levelW		= de::max(1, m_width >> ndx);
948			int		levelH		= de::max(1, m_height >> ndx);
949
950			int		w			= rnd.getInt(1, levelW);
951			int		h			= rnd.getInt(1, levelH);
952			int		x			= rnd.getInt(0, levelW-w);
953			int		y			= rnd.getInt(0, levelH-h);
954
955			Vec4	colorA		= randomVector<4>(rnd);
956			Vec4	colorB		= randomVector<4>(rnd);
957			int		cellSize	= rnd.getInt(2, 16);
958
959			data.setSize(w, h);
960			tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
961
962			glTexSubImage2D(GL_TEXTURE_2D, ndx, x, y, w, h, m_format, m_dataType, data.getAccess().getDataPtr());
963		}
964	}
965
966	deUint32	m_format;
967	deUint32	m_dataType;
968};
969
970// Basic TexSubImage2D() with cubemap usage
971class BasicTexSubImageCubeCase : public TextureSpecCase
972{
973public:
974	BasicTexSubImageCubeCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height)
975		: TextureSpecCase	(context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags, width, height)
976		, m_format			(format)
977		, m_dataType		(dataType)
978	{
979	}
980
981protected:
982	void createTexture (void)
983	{
984		tcu::TextureFormat	fmt			= m_texFormat;
985		int					numLevels	= (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1;
986		deUint32			tex			= 0;
987		tcu::TextureLevel	data		(fmt);
988		de::Random			rnd			(deStringHash(getName()));
989
990		DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2.
991
992		glGenTextures(1, &tex);
993		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
994		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
995
996		for (int ndx = 0; ndx < numLevels; ndx++)
997		{
998			int		levelW		= de::max(1, m_width >> ndx);
999			int		levelH		= de::max(1, m_height >> ndx);
1000
1001			data.setSize(levelW, levelH);
1002
1003			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1004			{
1005				Vec4 gMin = randomVector<4>(rnd);
1006				Vec4 gMax = randomVector<4>(rnd);
1007
1008				tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
1009
1010				glTexImage2D(s_cubeMapFaces[face], ndx, m_format, levelW, levelH, 0, m_format, m_dataType, data.getAccess().getDataPtr());
1011			}
1012		}
1013
1014		// Re-specify parts of each face and level.
1015		for (int ndx = 0; ndx < numLevels; ndx++)
1016		{
1017			int		levelW		= de::max(1, m_width >> ndx);
1018			int		levelH		= de::max(1, m_height >> ndx);
1019
1020			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1021			{
1022				int		w			= rnd.getInt(1, levelW);
1023				int		h			= rnd.getInt(1, levelH);
1024				int		x			= rnd.getInt(0, levelW-w);
1025				int		y			= rnd.getInt(0, levelH-h);
1026
1027				Vec4	colorA		= randomVector<4>(rnd);
1028				Vec4	colorB		= randomVector<4>(rnd);
1029				int		cellSize	= rnd.getInt(2, 16);
1030
1031				data.setSize(w, h);
1032				tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
1033
1034				glTexSubImage2D(s_cubeMapFaces[face], ndx, x, y, w, h, m_format, m_dataType, data.getAccess().getDataPtr());
1035			}
1036		}
1037	}
1038
1039	deUint32	m_format;
1040	deUint32	m_dataType;
1041};
1042
1043// TexSubImage2D() to texture initialized with empty data
1044class TexSubImage2DEmptyTexCase : public TextureSpecCase
1045{
1046public:
1047	TexSubImage2DEmptyTexCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height)
1048		: TextureSpecCase	(context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width, height)
1049		, m_format			(format)
1050		, m_dataType		(dataType)
1051	{
1052	}
1053
1054protected:
1055	void createTexture (void)
1056	{
1057		tcu::TextureFormat	fmt			= m_texFormat;
1058		int					numLevels	= (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1;
1059		deUint32			tex			= 0;
1060		tcu::TextureLevel	data		(fmt);
1061		de::Random			rnd			(deStringHash(getName()));
1062
1063		glGenTextures(1, &tex);
1064		glBindTexture(GL_TEXTURE_2D, tex);
1065		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1066
1067		// First allocate storage for each level.
1068		for (int ndx = 0; ndx < numLevels; ndx++)
1069		{
1070			int		levelW		= de::max(1, m_width >> ndx);
1071			int		levelH		= de::max(1, m_height >> ndx);
1072
1073			glTexImage2D(GL_TEXTURE_2D, ndx, m_format, levelW, levelH, 0, m_format, m_dataType, DE_NULL);
1074		}
1075
1076		// Specify pixel data to all levels using glTexSubImage2D()
1077		for (int ndx = 0; ndx < numLevels; ndx++)
1078		{
1079			int		levelW		= de::max(1, m_width >> ndx);
1080			int		levelH		= de::max(1, m_height >> ndx);
1081			Vec4	gMin		= randomVector<4>(rnd);
1082			Vec4	gMax		= randomVector<4>(rnd);
1083
1084			data.setSize(levelW, levelH);
1085			tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
1086
1087			glTexSubImage2D(GL_TEXTURE_2D, ndx, 0, 0, levelW, levelH, m_format, m_dataType, data.getAccess().getDataPtr());
1088		}
1089	}
1090
1091	deUint32	m_format;
1092	deUint32	m_dataType;
1093};
1094
1095// TexSubImage2D() to empty cubemap texture
1096class TexSubImageCubeEmptyTexCase : public TextureSpecCase
1097{
1098public:
1099	TexSubImageCubeEmptyTexCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height)
1100		: TextureSpecCase	(context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags, width, height)
1101		, m_format			(format)
1102		, m_dataType		(dataType)
1103	{
1104	}
1105
1106protected:
1107	void createTexture (void)
1108	{
1109		tcu::TextureFormat	fmt			= m_texFormat;
1110		int					numLevels	= (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1;
1111		deUint32			tex			= 0;
1112		tcu::TextureLevel	data		(fmt);
1113		de::Random			rnd			(deStringHash(getName()));
1114
1115		DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2.
1116
1117		glGenTextures(1, &tex);
1118		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1119		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1120
1121		// Specify storage for each level.
1122		for (int ndx = 0; ndx < numLevels; ndx++)
1123		{
1124			int		levelW		= de::max(1, m_width >> ndx);
1125			int		levelH		= de::max(1, m_height >> ndx);
1126
1127			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1128				glTexImage2D(s_cubeMapFaces[face], ndx, m_format, levelW, levelH, 0, m_format, m_dataType, DE_NULL);
1129		}
1130
1131		// Specify data using glTexSubImage2D()
1132		for (int ndx = 0; ndx < numLevels; ndx++)
1133		{
1134			int		levelW		= de::max(1, m_width >> ndx);
1135			int		levelH		= de::max(1, m_height >> ndx);
1136
1137			data.setSize(levelW, levelH);
1138
1139			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1140			{
1141				Vec4 gMin = randomVector<4>(rnd);
1142				Vec4 gMax = randomVector<4>(rnd);
1143
1144				tcu::fillWithComponentGradients(data.getAccess(), gMin, gMax);
1145
1146				glTexSubImage2D(s_cubeMapFaces[face], ndx, 0, 0, levelW, levelH, m_format, m_dataType, data.getAccess().getDataPtr());
1147			}
1148		}
1149	}
1150
1151	deUint32	m_format;
1152	deUint32	m_dataType;
1153};
1154
1155// TexSubImage2D() unpack alignment with 2D texture
1156class TexSubImage2DAlignCase : public TextureSpecCase
1157{
1158public:
1159	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)
1160		: TextureSpecCase	(context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), 0 /* Mipmaps are never used */, width, height)
1161		, m_format			(format)
1162		, m_dataType		(dataType)
1163		, m_subX			(subX)
1164		, m_subY			(subY)
1165		, m_subW			(subW)
1166		, m_subH			(subH)
1167		, m_alignment		(alignment)
1168	{
1169	}
1170
1171protected:
1172	void createTexture (void)
1173	{
1174		tcu::TextureFormat	fmt			= m_texFormat;
1175		deUint32			tex			= 0;
1176		vector<deUint8>		data;
1177
1178		glGenTextures(1, &tex);
1179		glBindTexture(GL_TEXTURE_2D, tex);
1180
1181		// Specify base level.
1182		data.resize(fmt.getPixelSize()*m_width*m_height);
1183		tcu::fillWithComponentGradients(tcu::PixelBufferAccess(fmt, m_width, m_height, 1, &data[0]), Vec4(0.0f), Vec4(1.0f));
1184
1185		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1186		glTexImage2D(GL_TEXTURE_2D, 0, m_format, m_width, m_height, 0, m_format, m_dataType, &data[0]);
1187
1188		// Re-specify subrectangle.
1189		int rowPitch = getRowPitch(fmt, m_subW, m_alignment);
1190		data.resize(rowPitch*m_subH);
1191		tcu::fillWithGrid(tcu::PixelBufferAccess(fmt, 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));
1192
1193		glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
1194		glTexSubImage2D(GL_TEXTURE_2D, 0, m_subX, m_subY, m_subW, m_subH, m_format, m_dataType, &data[0]);
1195	}
1196
1197	deUint32	m_format;
1198	deUint32	m_dataType;
1199	int			m_subX;
1200	int			m_subY;
1201	int			m_subW;
1202	int			m_subH;
1203	int			m_alignment;
1204};
1205
1206// TexSubImage2D() unpack alignment with cubemap texture
1207class TexSubImageCubeAlignCase : public TextureSpecCase
1208{
1209public:
1210	TexSubImageCubeAlignCase (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)
1211		: TextureSpecCase	(context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), 0 /* Mipmaps are never used */, width, height)
1212		, m_format			(format)
1213		, m_dataType		(dataType)
1214		, m_subX			(subX)
1215		, m_subY			(subY)
1216		, m_subW			(subW)
1217		, m_subH			(subH)
1218		, m_alignment		(alignment)
1219	{
1220	}
1221
1222protected:
1223	void createTexture (void)
1224	{
1225		tcu::TextureFormat	fmt			= m_texFormat;
1226		deUint32			tex			= 0;
1227		vector<deUint8>		data;
1228
1229		DE_ASSERT(m_width == m_height);
1230
1231		glGenTextures(1, &tex);
1232		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1233
1234		// Specify base level.
1235		data.resize(fmt.getPixelSize()*m_width*m_height);
1236		tcu::fillWithComponentGradients(tcu::PixelBufferAccess(fmt, m_width, m_height, 1, &data[0]), Vec4(0.0f), Vec4(1.0f));
1237
1238		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1239		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
1240			glTexImage2D(s_cubeMapFaces[face], 0, m_format, m_width, m_height, 0, m_format, m_dataType, &data[0]);
1241
1242		// Re-specify subrectangle.
1243		int rowPitch = getRowPitch(fmt, m_subW, m_alignment);
1244		data.resize(rowPitch*m_subH);
1245		tcu::fillWithGrid(tcu::PixelBufferAccess(fmt, 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));
1246
1247		glPixelStorei(GL_UNPACK_ALIGNMENT, m_alignment);
1248		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
1249			glTexSubImage2D(s_cubeMapFaces[face], 0, m_subX, m_subY, m_subW, m_subH, m_format, m_dataType, &data[0]);
1250	}
1251
1252	deUint32	m_format;
1253	deUint32	m_dataType;
1254	int			m_subX;
1255	int			m_subY;
1256	int			m_subW;
1257	int			m_subH;
1258	int			m_alignment;
1259};
1260
1261
1262
1263// Basic CopyTexImage2D() with 2D texture usage
1264class BasicCopyTexImage2DCase : public TextureSpecCase
1265{
1266public:
1267	BasicCopyTexImage2DCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, deUint32 flags, int width, int height)
1268		: TextureSpecCase	(context, name, desc, TEXTURETYPE_2D, mapGLUnsizedInternalFormat(internalFormat), flags, width, height)
1269		, m_internalFormat	(internalFormat)
1270	{
1271	}
1272
1273protected:
1274	void createTexture (void)
1275	{
1276		const tcu::RenderTarget&	renderTarget	= TestCase::m_context.getRenderContext().getRenderTarget();
1277		bool						targetHasRGB	= renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 && renderTarget.getPixelFormat().blueBits > 0;
1278		bool						targetHasAlpha	= renderTarget.getPixelFormat().alphaBits > 0;
1279		tcu::TextureFormat			fmt				= m_texFormat;
1280		bool						texHasRGB		= fmt.order != tcu::TextureFormat::A;
1281		bool						texHasAlpha		= fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA || fmt.order == tcu::TextureFormat::A;
1282		int							numLevels		= (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1;
1283		deUint32					tex				= 0;
1284		de::Random					rnd				(deStringHash(getName()));
1285		GradientShader				shader;
1286		deUint32					shaderID		= getCurrentContext()->createProgram(&shader);
1287
1288		if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
1289			throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__);
1290
1291		// Fill render target with gradient.
1292		sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f));
1293
1294		glGenTextures(1, &tex);
1295		glBindTexture(GL_TEXTURE_2D, tex);
1296
1297		for (int ndx = 0; ndx < numLevels; ndx++)
1298		{
1299			int		levelW		= de::max(1, m_width >> ndx);
1300			int		levelH		= de::max(1, m_height >> ndx);
1301			int		x			= rnd.getInt(0, getWidth()	- levelW);
1302			int		y			= rnd.getInt(0, getHeight()	- levelH);
1303
1304			glCopyTexImage2D(GL_TEXTURE_2D, ndx, m_internalFormat, x, y, levelW, levelH, 0);
1305		}
1306	}
1307
1308	deUint32 m_internalFormat;
1309};
1310
1311// Basic CopyTexImage2D() with cubemap usage
1312class BasicCopyTexImageCubeCase : public TextureSpecCase
1313{
1314public:
1315	BasicCopyTexImageCubeCase (Context& context, const char* name, const char* desc, deUint32 internalFormat, deUint32 flags, int width, int height)
1316		: TextureSpecCase	(context, name, desc, TEXTURETYPE_CUBE, mapGLUnsizedInternalFormat(internalFormat), flags, width, height)
1317		, m_internalFormat	(internalFormat)
1318	{
1319	}
1320
1321protected:
1322	void createTexture (void)
1323	{
1324		const tcu::RenderTarget&	renderTarget	= TestCase::m_context.getRenderContext().getRenderTarget();
1325		bool						targetHasRGB	= renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 && renderTarget.getPixelFormat().blueBits > 0;
1326		bool						targetHasAlpha	= renderTarget.getPixelFormat().alphaBits > 0;
1327		tcu::TextureFormat			fmt				= m_texFormat;
1328		bool						texHasRGB		= fmt.order != tcu::TextureFormat::A;
1329		bool						texHasAlpha		= fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA || fmt.order == tcu::TextureFormat::A;
1330		int							numLevels		= (m_flags & MIPMAPS) ? deLog2Floor32(m_width)+1 : 1;
1331		deUint32					tex				= 0;
1332		de::Random					rnd				(deStringHash(getName()));
1333		GradientShader				shader;
1334		deUint32					shaderID		= getCurrentContext()->createProgram(&shader);
1335
1336		DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2.
1337
1338		if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
1339			throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__);
1340
1341		// Fill render target with gradient.
1342		sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f));
1343
1344		glGenTextures(1, &tex);
1345		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1346
1347		for (int ndx = 0; ndx < numLevels; ndx++)
1348		{
1349			int levelW = de::max(1, m_width >> ndx);
1350			int levelH = de::max(1, m_height >> ndx);
1351
1352			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1353			{
1354				int x = rnd.getInt(0, getWidth()	- levelW);
1355				int y = rnd.getInt(0, getHeight()	- levelH);
1356
1357				glCopyTexImage2D(s_cubeMapFaces[face], ndx, m_internalFormat, x, y, levelW, levelH, 0);
1358			}
1359		}
1360	}
1361
1362	deUint32 m_internalFormat;
1363};
1364
1365
1366
1367// Basic CopyTexSubImage2D() with 2D texture usage
1368class BasicCopyTexSubImage2DCase : public TextureSpecCase
1369{
1370public:
1371	BasicCopyTexSubImage2DCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height)
1372		: TextureSpecCase	(context, name, desc, TEXTURETYPE_2D, glu::mapGLTransferFormat(format, dataType), flags, width, height)
1373		, m_format			(format)
1374		, m_dataType		(dataType)
1375	{
1376	}
1377
1378protected:
1379	void createTexture (void)
1380	{
1381		const tcu::RenderTarget&	renderTarget	= TestCase::m_context.getRenderContext().getRenderTarget();
1382		bool						targetHasRGB	= renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 && renderTarget.getPixelFormat().blueBits > 0;
1383		bool						targetHasAlpha	= renderTarget.getPixelFormat().alphaBits > 0;
1384		tcu::TextureFormat			fmt				= m_texFormat;
1385		bool						texHasRGB		= fmt.order != tcu::TextureFormat::A;
1386		bool						texHasAlpha		= fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA || fmt.order == tcu::TextureFormat::A;
1387		int							numLevels		= (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1;
1388		deUint32					tex				= 0;
1389		tcu::TextureLevel			data			(fmt);
1390		de::Random					rnd				(deStringHash(getName()));
1391		GradientShader				shader;
1392		deUint32					shaderID		= getCurrentContext()->createProgram(&shader);
1393
1394		if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
1395			throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__);
1396
1397		glGenTextures(1, &tex);
1398		glBindTexture(GL_TEXTURE_2D, tex);
1399		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1400
1401		// First specify full texture.
1402		for (int ndx = 0; ndx < numLevels; ndx++)
1403		{
1404			int		levelW		= de::max(1, m_width >> ndx);
1405			int		levelH		= de::max(1, m_height >> ndx);
1406
1407			Vec4	colorA		= randomVector<4>(rnd);
1408			Vec4	colorB		= randomVector<4>(rnd);
1409			int		cellSize	= rnd.getInt(2, 16);
1410
1411			data.setSize(levelW, levelH);
1412			tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
1413
1414			glTexImage2D(GL_TEXTURE_2D, ndx, m_format, levelW, levelH, 0, m_format, m_dataType, data.getAccess().getDataPtr());
1415		}
1416
1417		// Fill render target with gradient.
1418		sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f));
1419
1420		// Re-specify parts of each level.
1421		for (int ndx = 0; ndx < numLevels; ndx++)
1422		{
1423			int		levelW		= de::max(1, m_width >> ndx);
1424			int		levelH		= de::max(1, m_height >> ndx);
1425
1426			int		w			= rnd.getInt(1, levelW);
1427			int		h			= rnd.getInt(1, levelH);
1428			int		xo			= rnd.getInt(0, levelW-w);
1429			int		yo			= rnd.getInt(0, levelH-h);
1430
1431			int		x			= rnd.getInt(0, getWidth() - w);
1432			int		y			= rnd.getInt(0, getHeight() - h);
1433
1434			glCopyTexSubImage2D(GL_TEXTURE_2D, ndx, xo, yo, x, y, w, h);
1435		}
1436	}
1437
1438	deUint32	m_format;
1439	deUint32	m_dataType;
1440};
1441
1442// Basic CopyTexSubImage2D() with cubemap usage
1443class BasicCopyTexSubImageCubeCase : public TextureSpecCase
1444{
1445public:
1446	BasicCopyTexSubImageCubeCase (Context& context, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 flags, int width, int height)
1447		: TextureSpecCase	(context, name, desc, TEXTURETYPE_CUBE, glu::mapGLTransferFormat(format, dataType), flags, width, height)
1448		, m_format			(format)
1449		, m_dataType		(dataType)
1450	{
1451	}
1452
1453protected:
1454	void createTexture (void)
1455	{
1456		const tcu::RenderTarget&	renderTarget	= TestCase::m_context.getRenderContext().getRenderTarget();
1457		bool						targetHasRGB	= renderTarget.getPixelFormat().redBits > 0 && renderTarget.getPixelFormat().greenBits > 0 && renderTarget.getPixelFormat().blueBits > 0;
1458		bool						targetHasAlpha	= renderTarget.getPixelFormat().alphaBits > 0;
1459		tcu::TextureFormat			fmt				= m_texFormat;
1460		bool						texHasRGB		= fmt.order != tcu::TextureFormat::A;
1461		bool						texHasAlpha		= fmt.order == tcu::TextureFormat::RGBA || fmt.order == tcu::TextureFormat::LA || fmt.order == tcu::TextureFormat::A;
1462		int							numLevels		= (m_flags & MIPMAPS) ? de::max(deLog2Floor32(m_width), deLog2Floor32(m_height))+1 : 1;
1463		deUint32					tex				= 0;
1464		tcu::TextureLevel			data			(fmt);
1465		de::Random					rnd				(deStringHash(getName()));
1466		GradientShader				shader;
1467		deUint32					shaderID		= getCurrentContext()->createProgram(&shader);
1468
1469		DE_ASSERT(m_width == m_height); // Non-square cubemaps are not supported by GLES2.
1470
1471		if ((texHasRGB && !targetHasRGB) || (texHasAlpha && !targetHasAlpha))
1472			throw tcu::NotSupportedError("Copying from current framebuffer is not supported", "", __FILE__, __LINE__);
1473
1474		glGenTextures(1, &tex);
1475		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
1476		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1477
1478		for (int ndx = 0; ndx < numLevels; ndx++)
1479		{
1480			int		levelW		= de::max(1, m_width >> ndx);
1481			int		levelH		= de::max(1, m_height >> ndx);
1482
1483			data.setSize(levelW, levelH);
1484
1485			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1486			{
1487				Vec4	colorA		= randomVector<4>(rnd);
1488				Vec4	colorB		= randomVector<4>(rnd);
1489				int		cellSize	= rnd.getInt(2, 16);
1490
1491				tcu::fillWithGrid(data.getAccess(), cellSize, colorA, colorB);
1492				glTexImage2D(s_cubeMapFaces[face], ndx, m_format, levelW, levelH, 0, m_format, m_dataType, data.getAccess().getDataPtr());
1493			}
1494		}
1495
1496		// Fill render target with gradient.
1497		sglr::drawQuad(*getCurrentContext(), shaderID, tcu::Vec3(-1.0f, -1.0f, 0.0f), tcu::Vec3(1.0f, 1.0f, 0.0f));
1498
1499		// Re-specify parts of each face and level.
1500		for (int ndx = 0; ndx < numLevels; ndx++)
1501		{
1502			int		levelW		= de::max(1, m_width >> ndx);
1503			int		levelH		= de::max(1, m_height >> ndx);
1504
1505			for (int face = 0; face < DE_LENGTH_OF_ARRAY(s_cubeMapFaces); face++)
1506			{
1507				int		w			= rnd.getInt(1, levelW);
1508				int		h			= rnd.getInt(1, levelH);
1509				int		xo			= rnd.getInt(0, levelW-w);
1510				int		yo			= rnd.getInt(0, levelH-h);
1511
1512				int		x			= rnd.getInt(0, getWidth() - w);
1513				int		y			= rnd.getInt(0, getHeight() - h);
1514
1515				glCopyTexSubImage2D(s_cubeMapFaces[face], ndx, xo, yo, x, y, w, h);
1516			}
1517		}
1518	}
1519
1520	deUint32	m_format;
1521	deUint32	m_dataType;
1522};
1523
1524TextureSpecificationTests::TextureSpecificationTests (Context& context)
1525	: TestCaseGroup(context, "specification", "Texture Specification Tests")
1526{
1527}
1528
1529TextureSpecificationTests::~TextureSpecificationTests (void)
1530{
1531}
1532
1533void TextureSpecificationTests::init (void)
1534{
1535	struct
1536	{
1537		const char*	name;
1538		deUint32	format;
1539		deUint32	dataType;
1540	} texFormats[] =
1541	{
1542		{ "a8",			GL_ALPHA,			GL_UNSIGNED_BYTE },
1543		{ "l8",			GL_LUMINANCE,		GL_UNSIGNED_BYTE },
1544		{ "la88",		GL_LUMINANCE_ALPHA,	GL_UNSIGNED_BYTE },
1545		{ "rgb565",		GL_RGB,				GL_UNSIGNED_SHORT_5_6_5 },
1546		{ "rgb888",		GL_RGB,				GL_UNSIGNED_BYTE },
1547		{ "rgba4444",	GL_RGBA,			GL_UNSIGNED_SHORT_4_4_4_4 },
1548		{ "rgba5551",	GL_RGBA,			GL_UNSIGNED_SHORT_5_5_5_1 },
1549		{ "rgba8888",	GL_RGBA,			GL_UNSIGNED_BYTE }
1550	};
1551
1552	// Basic TexImage2D usage.
1553	{
1554		tcu::TestCaseGroup* basicTexImageGroup = new tcu::TestCaseGroup(m_testCtx, "basic_teximage2d", "Basic glTexImage2D() usage");
1555		addChild(basicTexImageGroup);
1556		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(texFormats); formatNdx++)
1557		{
1558			const char*	fmtName		= texFormats[formatNdx].name;
1559			deUint32	format		= texFormats[formatNdx].format;
1560			deUint32	dataType	= texFormats[formatNdx].dataType;
1561			const int	tex2DWidth	= 64;
1562			const int	tex2DHeight	= 128;
1563			const int	texCubeSize	= 64;
1564
1565			basicTexImageGroup->addChild(new BasicTexImage2DCase	(m_context,	(string(fmtName) + "_2d").c_str(),		"",	format, dataType, MIPMAPS, tex2DWidth, tex2DHeight));
1566			basicTexImageGroup->addChild(new BasicTexImageCubeCase	(m_context,	(string(fmtName) + "_cube").c_str(),	"",	format, dataType, MIPMAPS, texCubeSize, texCubeSize));
1567		}
1568	}
1569
1570	// Randomized TexImage2D order.
1571	{
1572		tcu::TestCaseGroup* randomTexImageGroup = new tcu::TestCaseGroup(m_testCtx, "random_teximage2d", "Randomized glTexImage2D() usage");
1573		addChild(randomTexImageGroup);
1574
1575		de::Random rnd(9);
1576
1577		// 2D cases.
1578		for (int ndx = 0; ndx < 10; ndx++)
1579		{
1580			int		formatNdx	= rnd.getInt(0, DE_LENGTH_OF_ARRAY(texFormats)-1);
1581			int		width		= 1 << rnd.getInt(2, 8);
1582			int		height		= 1 << rnd.getInt(2, 8);
1583
1584			randomTexImageGroup->addChild(new RandomOrderTexImage2DCase(m_context, (string("2d_") + de::toString(ndx)).c_str(), "", texFormats[formatNdx].format, texFormats[formatNdx].dataType, MIPMAPS, width, height));
1585		}
1586
1587		// Cubemap cases.
1588		for (int ndx = 0; ndx < 10; ndx++)
1589		{
1590			int		formatNdx	= rnd.getInt(0, DE_LENGTH_OF_ARRAY(texFormats)-1);
1591			int		size		= 1 << rnd.getInt(2, 8);
1592
1593			randomTexImageGroup->addChild(new RandomOrderTexImageCubeCase(m_context, (string("cube_") + de::toString(ndx)).c_str(), "", texFormats[formatNdx].format, texFormats[formatNdx].dataType, MIPMAPS, size, size));
1594		}
1595	}
1596
1597	// TexImage2D unpack alignment.
1598	{
1599		tcu::TestCaseGroup* alignGroup = new tcu::TestCaseGroup(m_testCtx, "teximage2d_align", "glTexImage2D() unpack alignment tests");
1600		addChild(alignGroup);
1601
1602		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_l8_4_8",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			MIPMAPS,	 4, 8, 8));
1603		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_l8_63_1",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			0,			63, 30, 1));
1604		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_l8_63_2",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			0,			63, 30, 2));
1605		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_l8_63_4",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			0,			63, 30, 4));
1606		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_l8_63_8",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			0,			63, 30, 8));
1607		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgba4444_51_1",		"",	GL_RGBA,		GL_UNSIGNED_SHORT_4_4_4_4,	0,			51, 30, 1));
1608		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgba4444_51_2",		"",	GL_RGBA,		GL_UNSIGNED_SHORT_4_4_4_4,	0,			51, 30, 2));
1609		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgba4444_51_4",		"",	GL_RGBA,		GL_UNSIGNED_SHORT_4_4_4_4,	0,			51, 30, 4));
1610		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgba4444_51_8",		"",	GL_RGBA,		GL_UNSIGNED_SHORT_4_4_4_4,	0,			51, 30, 8));
1611		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgb888_39_1",		"",	GL_RGB,			GL_UNSIGNED_BYTE,			0,			39, 43, 1));
1612		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgb888_39_2",		"",	GL_RGB,			GL_UNSIGNED_BYTE,			0,			39, 43, 2));
1613		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgb888_39_4",		"",	GL_RGB,			GL_UNSIGNED_BYTE,			0,			39, 43, 4));
1614		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgb888_39_8",		"",	GL_RGB,			GL_UNSIGNED_BYTE,			0,			39, 43, 8));
1615		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgba8888_47_1",		"",	GL_RGBA,		GL_UNSIGNED_BYTE,			0,			47, 27, 1));
1616		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgba8888_47_2",		"",	GL_RGBA,		GL_UNSIGNED_BYTE,			0,			47, 27, 2));
1617		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgba8888_47_4",		"",	GL_RGBA,		GL_UNSIGNED_BYTE,			0,			47, 27, 4));
1618		alignGroup->addChild(new TexImage2DAlignCase	(m_context, "2d_rgba8888_47_8",		"",	GL_RGBA,		GL_UNSIGNED_BYTE,			0,			47, 27, 8));
1619
1620		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_l8_4_8",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			MIPMAPS,	 4, 4, 8));
1621		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_l8_63_1",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			0,			63, 63, 1));
1622		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_l8_63_2",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			0,			63, 63, 2));
1623		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_l8_63_4",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			0,			63, 63, 4));
1624		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_l8_63_8",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			0,			63, 63, 8));
1625		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgba4444_51_1",	"",	GL_RGBA,		GL_UNSIGNED_SHORT_4_4_4_4,	0,			51, 51, 1));
1626		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgba4444_51_2",	"",	GL_RGBA,		GL_UNSIGNED_SHORT_4_4_4_4,	0,			51, 51, 2));
1627		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgba4444_51_4",	"",	GL_RGBA,		GL_UNSIGNED_SHORT_4_4_4_4,	0,			51, 51, 4));
1628		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgba4444_51_8",	"",	GL_RGBA,		GL_UNSIGNED_SHORT_4_4_4_4,	0,			51, 51, 8));
1629		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgb888_39_1",		"",	GL_RGB,			GL_UNSIGNED_BYTE,			0,			39, 39, 1));
1630		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgb888_39_2",		"",	GL_RGB,			GL_UNSIGNED_BYTE,			0,			39, 39, 2));
1631		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgb888_39_4",		"",	GL_RGB,			GL_UNSIGNED_BYTE,			0,			39, 39, 4));
1632		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgb888_39_8",		"",	GL_RGB,			GL_UNSIGNED_BYTE,			0,			39, 39, 8));
1633		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgba8888_47_1",	"",	GL_RGBA,		GL_UNSIGNED_BYTE,			0,			47, 47, 1));
1634		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgba8888_47_2",	"",	GL_RGBA,		GL_UNSIGNED_BYTE,			0,			47, 47, 2));
1635		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgba8888_47_4",	"",	GL_RGBA,		GL_UNSIGNED_BYTE,			0,			47, 47, 4));
1636		alignGroup->addChild(new TexImageCubeAlignCase	(m_context, "cube_rgba8888_47_8",	"",	GL_RGBA,		GL_UNSIGNED_BYTE,			0,			47, 47, 8));
1637	}
1638
1639	// Basic TexSubImage2D usage.
1640	{
1641		tcu::TestCaseGroup* basicTexSubImageGroup = new tcu::TestCaseGroup(m_testCtx, "basic_texsubimage2d", "Basic glTexSubImage2D() usage");
1642		addChild(basicTexSubImageGroup);
1643		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(texFormats); formatNdx++)
1644		{
1645			const char*	fmtName		= texFormats[formatNdx].name;
1646			deUint32	format		= texFormats[formatNdx].format;
1647			deUint32	dataType	= texFormats[formatNdx].dataType;
1648			const int	tex2DWidth	= 64;
1649			const int	tex2DHeight	= 128;
1650			const int	texCubeSize	= 64;
1651
1652			basicTexSubImageGroup->addChild(new BasicTexSubImage2DCase		(m_context,	(string(fmtName) + "_2d").c_str(),		"",	format, dataType, MIPMAPS, tex2DWidth, tex2DHeight));
1653			basicTexSubImageGroup->addChild(new BasicTexSubImageCubeCase	(m_context,	(string(fmtName) + "_cube").c_str(),	"",	format, dataType, MIPMAPS, texCubeSize, texCubeSize));
1654		}
1655	}
1656
1657	// TexSubImage2D to empty texture.
1658	{
1659		tcu::TestCaseGroup* texSubImageEmptyTexGroup = new tcu::TestCaseGroup(m_testCtx, "texsubimage2d_empty_tex", "glTexSubImage2D() to texture that has storage but no data");
1660		addChild(texSubImageEmptyTexGroup);
1661		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(texFormats); formatNdx++)
1662		{
1663			const char*	fmtName		= texFormats[formatNdx].name;
1664			deUint32	format		= texFormats[formatNdx].format;
1665			deUint32	dataType	= texFormats[formatNdx].dataType;
1666			const int	tex2DWidth	= 64;
1667			const int	tex2DHeight	= 32;
1668			const int	texCubeSize	= 32;
1669
1670			texSubImageEmptyTexGroup->addChild(new TexSubImage2DEmptyTexCase	(m_context,	(string(fmtName) + "_2d").c_str(),		"",	format, dataType, MIPMAPS, tex2DWidth, tex2DHeight));
1671			texSubImageEmptyTexGroup->addChild(new TexSubImageCubeEmptyTexCase	(m_context,	(string(fmtName) + "_cube").c_str(),	"",	format, dataType, MIPMAPS, texCubeSize, texCubeSize));
1672		}
1673	}
1674
1675	// TexSubImage2D alignment cases.
1676	{
1677		tcu::TestCaseGroup* alignGroup = new tcu::TestCaseGroup(m_testCtx, "texsubimage2d_align", "glTexSubImage2D() unpack alignment tests");
1678		addChild(alignGroup);
1679
1680		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_l8_1_1",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			64, 64, 13, 17,  1,  6, 1));
1681		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_l8_1_2",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			64, 64, 13, 17,  1,  6, 2));
1682		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_l8_1_4",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			64, 64, 13, 17,  1,  6, 4));
1683		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_l8_1_8",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			64, 64, 13, 17,  1,  6, 8));
1684		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_l8_63_1",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			64, 64,  1,  9, 63, 30, 1));
1685		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_l8_63_2",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			64, 64,  1,  9, 63, 30, 2));
1686		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_l8_63_4",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			64, 64,  1,  9, 63, 30, 4));
1687		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_l8_63_8",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			64, 64,  1,  9, 63, 30, 8));
1688		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgba4444_51_1",		"",	GL_RGBA,		GL_UNSIGNED_SHORT_4_4_4_4,	64, 64,  7, 29, 51, 30, 1));
1689		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgba4444_51_2",		"",	GL_RGBA,		GL_UNSIGNED_SHORT_4_4_4_4,	64, 64,  7, 29, 51, 30, 2));
1690		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgba4444_51_4",		"",	GL_RGBA,		GL_UNSIGNED_SHORT_4_4_4_4,	64, 64,  7, 29, 51, 30, 4));
1691		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgba4444_51_8",		"",	GL_RGBA,		GL_UNSIGNED_SHORT_4_4_4_4,	64, 64,  7, 29, 51, 30, 8));
1692		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgb888_39_1",		"",	GL_RGB,			GL_UNSIGNED_BYTE,			64, 64, 11,  8, 39, 43, 1));
1693		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgb888_39_2",		"",	GL_RGB,			GL_UNSIGNED_BYTE,			64, 64, 11,  8, 39, 43, 2));
1694		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgb888_39_4",		"",	GL_RGB,			GL_UNSIGNED_BYTE,			64, 64, 11,  8, 39, 43, 4));
1695		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgb888_39_8",		"",	GL_RGB,			GL_UNSIGNED_BYTE,			64, 64, 11,  8, 39, 43, 8));
1696		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgba8888_47_1",		"",	GL_RGBA,		GL_UNSIGNED_BYTE,			64, 64, 10,  1, 47, 27, 1));
1697		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgba8888_47_2",		"",	GL_RGBA,		GL_UNSIGNED_BYTE,			64, 64, 10,  1, 47, 27, 2));
1698		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgba8888_47_4",		"",	GL_RGBA,		GL_UNSIGNED_BYTE,			64, 64, 10,  1, 47, 27, 4));
1699		alignGroup->addChild(new TexSubImage2DAlignCase		(m_context, "2d_rgba8888_47_8",		"",	GL_RGBA,		GL_UNSIGNED_BYTE,			64, 64, 10,  1, 47, 27, 8));
1700
1701		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_l8_1_1",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			64, 64, 13, 17,  1,  6, 1));
1702		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_l8_1_2",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			64, 64, 13, 17,  1,  6, 2));
1703		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_l8_1_4",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			64, 64, 13, 17,  1,  6, 4));
1704		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_l8_1_8",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			64, 64, 13, 17,  1,  6, 8));
1705		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_l8_63_1",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			64, 64,  1,  9, 63, 30, 1));
1706		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_l8_63_2",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			64, 64,  1,  9, 63, 30, 2));
1707		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_l8_63_4",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			64, 64,  1,  9, 63, 30, 4));
1708		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_l8_63_8",			"",	GL_LUMINANCE,	GL_UNSIGNED_BYTE,			64, 64,  1,  9, 63, 30, 8));
1709		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgba4444_51_1",	"",	GL_RGBA,		GL_UNSIGNED_SHORT_4_4_4_4,	64, 64,  7, 29, 51, 30, 1));
1710		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgba4444_51_2",	"",	GL_RGBA,		GL_UNSIGNED_SHORT_4_4_4_4,	64, 64,  7, 29, 51, 30, 2));
1711		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgba4444_51_4",	"",	GL_RGBA,		GL_UNSIGNED_SHORT_4_4_4_4,	64, 64,  7, 29, 51, 30, 4));
1712		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgba4444_51_8",	"",	GL_RGBA,		GL_UNSIGNED_SHORT_4_4_4_4,	64, 64,  7, 29, 51, 30, 8));
1713		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgb888_39_1",		"",	GL_RGB,			GL_UNSIGNED_BYTE,			64, 64, 11,  8, 39, 43, 1));
1714		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgb888_39_2",		"",	GL_RGB,			GL_UNSIGNED_BYTE,			64, 64, 11,  8, 39, 43, 2));
1715		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgb888_39_4",		"",	GL_RGB,			GL_UNSIGNED_BYTE,			64, 64, 11,  8, 39, 43, 4));
1716		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgb888_39_8",		"",	GL_RGB,			GL_UNSIGNED_BYTE,			64, 64, 11,  8, 39, 43, 8));
1717		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgba8888_47_1",	"",	GL_RGBA,		GL_UNSIGNED_BYTE,			64, 64, 10,  1, 47, 27, 1));
1718		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgba8888_47_2",	"",	GL_RGBA,		GL_UNSIGNED_BYTE,			64, 64, 10,  1, 47, 27, 2));
1719		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgba8888_47_4",	"",	GL_RGBA,		GL_UNSIGNED_BYTE,			64, 64, 10,  1, 47, 27, 4));
1720		alignGroup->addChild(new TexSubImageCubeAlignCase	(m_context, "cube_rgba8888_47_8",	"",	GL_RGBA,		GL_UNSIGNED_BYTE,			64, 64, 10,  1, 47, 27, 8));
1721	}
1722
1723	// Basic glCopyTexImage2D() cases
1724	{
1725		tcu::TestCaseGroup* copyTexImageGroup = new tcu::TestCaseGroup(m_testCtx, "basic_copyteximage2d", "Basic glCopyTexImage2D() usage");
1726		addChild(copyTexImageGroup);
1727
1728		copyTexImageGroup->addChild(new BasicCopyTexImage2DCase		(m_context, "2d_alpha",				"",	GL_ALPHA,			MIPMAPS,	128, 64));
1729		copyTexImageGroup->addChild(new BasicCopyTexImage2DCase		(m_context, "2d_luminance",			"",	GL_LUMINANCE,		MIPMAPS,	128, 64));
1730		copyTexImageGroup->addChild(new BasicCopyTexImage2DCase		(m_context, "2d_luminance_alpha",	"",	GL_LUMINANCE_ALPHA,	MIPMAPS,	128, 64));
1731		copyTexImageGroup->addChild(new BasicCopyTexImage2DCase		(m_context, "2d_rgb",				"",	GL_RGB,				MIPMAPS,	128, 64));
1732		copyTexImageGroup->addChild(new BasicCopyTexImage2DCase		(m_context, "2d_rgba",				"",	GL_RGBA,			MIPMAPS,	128, 64));
1733
1734		copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase	(m_context, "cube_alpha",			"",	GL_ALPHA,			MIPMAPS,	64, 64));
1735		copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase	(m_context, "cube_luminance",		"",	GL_LUMINANCE,		MIPMAPS,	64, 64));
1736		copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase	(m_context, "cube_luminance_alpha",	"",	GL_LUMINANCE_ALPHA,	MIPMAPS,	64, 64));
1737		copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase	(m_context, "cube_rgb",				"",	GL_RGB,				MIPMAPS,	64, 64));
1738		copyTexImageGroup->addChild(new BasicCopyTexImageCubeCase	(m_context, "cube_rgba",			"",	GL_RGBA,			MIPMAPS,	64, 64));
1739	}
1740
1741	// Basic glCopyTexSubImage2D() cases
1742	{
1743		tcu::TestCaseGroup* copyTexSubImageGroup = new tcu::TestCaseGroup(m_testCtx, "basic_copytexsubimage2d", "Basic glCopyTexSubImage2D() usage");
1744		addChild(copyTexSubImageGroup);
1745
1746		copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase	(m_context, "2d_alpha",				"",	GL_ALPHA,			GL_UNSIGNED_BYTE, MIPMAPS, 128, 64));
1747		copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase	(m_context, "2d_luminance",			"",	GL_LUMINANCE,		GL_UNSIGNED_BYTE, MIPMAPS, 128, 64));
1748		copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase	(m_context, "2d_luminance_alpha",	"",	GL_LUMINANCE_ALPHA,	GL_UNSIGNED_BYTE, MIPMAPS, 128, 64));
1749		copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase	(m_context, "2d_rgb",				"",	GL_RGB,				GL_UNSIGNED_BYTE, MIPMAPS, 128, 64));
1750		copyTexSubImageGroup->addChild(new BasicCopyTexSubImage2DCase	(m_context, "2d_rgba",				"",	GL_RGBA,			GL_UNSIGNED_BYTE, MIPMAPS, 128, 64));
1751
1752		copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase	(m_context, "cube_alpha",			"",	GL_ALPHA,			GL_UNSIGNED_BYTE, MIPMAPS, 64, 64));
1753		copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase	(m_context, "cube_luminance",		"",	GL_LUMINANCE,		GL_UNSIGNED_BYTE, MIPMAPS, 64, 64));
1754		copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase	(m_context, "cube_luminance_alpha",	"",	GL_LUMINANCE_ALPHA,	GL_UNSIGNED_BYTE, MIPMAPS, 64, 64));
1755		copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase	(m_context, "cube_rgb",				"",	GL_RGB,				GL_UNSIGNED_BYTE, MIPMAPS, 64, 64));
1756		copyTexSubImageGroup->addChild(new BasicCopyTexSubImageCubeCase	(m_context, "cube_rgba",			"",	GL_RGBA,			GL_UNSIGNED_BYTE, MIPMAPS, 64, 64));
1757	}
1758}
1759
1760} // Functional
1761} // gles2
1762} // deqp
1763