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