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