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