Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.0 Module
      3  * -------------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief FBO colorbuffer tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es3fFboColorbufferTests.hpp"
     25 #include "es3fFboTestCase.hpp"
     26 #include "es3fFboTestUtil.hpp"
     27 #include "gluTextureUtil.hpp"
     28 #include "gluContextInfo.hpp"
     29 #include "tcuImageCompare.hpp"
     30 #include "tcuRGBA.hpp"
     31 #include "tcuTestLog.hpp"
     32 #include "tcuTextureUtil.hpp"
     33 #include "sglrContextUtil.hpp"
     34 #include "deRandom.hpp"
     35 #include "deString.h"
     36 #include "glwEnums.hpp"
     37 
     38 namespace deqp
     39 {
     40 namespace gles3
     41 {
     42 namespace Functional
     43 {
     44 
     45 using std::string;
     46 using tcu::Vec2;
     47 using tcu::Vec3;
     48 using tcu::Vec4;
     49 using tcu::IVec2;
     50 using tcu::IVec3;
     51 using tcu::IVec4;
     52 using tcu::UVec4;
     53 using tcu::TestLog;
     54 using namespace FboTestUtil;
     55 
     56 const tcu::RGBA MIN_THRESHOLD(12, 12, 12, 12);
     57 
     58 template <int Size>
     59 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))
     60 {
     61 	tcu::Vector<float, Size> res;
     62 	for (int ndx = 0; ndx < Size; ndx++)
     63 		res[ndx] = rnd.getFloat(minVal[ndx], maxVal[ndx]);
     64 	return res;
     65 }
     66 
     67 static tcu::Vec4 generateRandomColor (de::Random& random)
     68 {
     69 	tcu::Vec4 retVal;
     70 
     71 	for (int i = 0; i < 3; ++i)
     72 		retVal[i] = random.getFloat();
     73 	retVal[3] = 1.0f;
     74 
     75 	return retVal;
     76 }
     77 
     78 class FboColorbufferCase : public FboTestCase
     79 {
     80 public:
     81 	FboColorbufferCase (Context& context, const char* name, const char* desc, const deUint32 format)
     82 		: FboTestCase			(context, name, desc)
     83 		, m_format				(format)
     84 	{
     85 	}
     86 
     87 	bool compare (const tcu::Surface& reference, const tcu::Surface& result)
     88 	{
     89 		const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_format), MIN_THRESHOLD));
     90 
     91 		m_testCtx.getLog() << TestLog::Message << "Comparing images, threshold: " << threshold << TestLog::EndMessage;
     92 
     93 		return tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
     94 	}
     95 
     96 protected:
     97 	const deUint32	m_format;
     98 };
     99 
    100 class FboColorClearCase : public FboColorbufferCase
    101 {
    102 public:
    103 	FboColorClearCase (Context& context, const char* name, const char* desc, deUint32 format, int width, int height)
    104 		: FboColorbufferCase	(context, name, desc, format)
    105 		, m_width				(width)
    106 		, m_height				(height)
    107 	{
    108 	}
    109 
    110 protected:
    111 	void preCheck (void)
    112 	{
    113 		checkFormatSupport(m_format);
    114 	}
    115 
    116 	void render (tcu::Surface& dst)
    117 	{
    118 		tcu::TextureFormat			fboFormat	= glu::mapGLInternalFormat(m_format);
    119 		tcu::TextureChannelClass	fmtClass	= tcu::getTextureChannelClass(fboFormat.type);
    120 		tcu::TextureFormatInfo		fmtInfo		= tcu::getTextureFormatInfo(fboFormat);
    121 		de::Random					rnd			(17);
    122 		const int					numClears	= 16;
    123 		deUint32					fbo			= 0;
    124 		deUint32					rbo			= 0;
    125 
    126 		glGenFramebuffers(1, &fbo);
    127 		glGenRenderbuffers(1, &rbo);
    128 
    129 		glBindRenderbuffer(GL_RENDERBUFFER, rbo);
    130 		glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_width, m_height);
    131 		checkError();
    132 
    133 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    134 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
    135 		checkError();
    136 		checkFramebufferStatus(GL_FRAMEBUFFER);
    137 
    138 		glViewport(0, 0, m_width, m_height);
    139 
    140 		// Initialize to transparent black.
    141 		switch (fmtClass)
    142 		{
    143 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
    144 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
    145 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
    146 				glClearBufferfv(GL_COLOR, 0, Vec4(0.0f).getPtr());
    147 				break;
    148 
    149 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
    150 				glClearBufferuiv(GL_COLOR, 0, UVec4(0).getPtr());
    151 				break;
    152 
    153 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
    154 				glClearBufferiv(GL_COLOR, 0, IVec4(0).getPtr());
    155 				break;
    156 
    157 			default:
    158 				DE_ASSERT(DE_FALSE);
    159 		}
    160 
    161 		// Do random scissored clears.
    162 		glEnable(GL_SCISSOR_TEST);
    163 		for (int ndx = 0; ndx < numClears; ndx++)
    164 		{
    165 			int		x		= rnd.getInt(0, m_width		- 1);
    166 			int		y		= rnd.getInt(0, m_height	- 1);
    167 			int		w		= rnd.getInt(1, m_width		- x);
    168 			int		h		= rnd.getInt(1, m_height	- y);
    169 			Vec4	color	= randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax);
    170 
    171 			glScissor(x, y, w, h);
    172 
    173 			switch (fmtClass)
    174 			{
    175 				case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
    176 				case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
    177 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
    178 					glClearBufferfv(GL_COLOR, 0, color.getPtr());
    179 					break;
    180 
    181 				case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
    182 					glClearBufferuiv(GL_COLOR, 0, color.cast<deUint32>().getPtr());
    183 					break;
    184 
    185 				case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
    186 					glClearBufferiv(GL_COLOR, 0, color.cast<int>().getPtr());
    187 					break;
    188 
    189 				default:
    190 					DE_ASSERT(DE_FALSE);
    191 			}
    192 		}
    193 
    194 		// Read results from renderbuffer.
    195 		readPixels(dst, 0, 0, m_width, m_height, fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias);
    196 		checkError();
    197 	}
    198 
    199 private:
    200 	const int			m_width;
    201 	const int			m_height;
    202 };
    203 
    204 class FboColorMultiTex2DCase : public FboColorbufferCase
    205 {
    206 public:
    207 	FboColorMultiTex2DCase (Context& context, const char* name, const char* description, deUint32 tex0Fmt, const IVec2& tex0Size, deUint32 tex1Fmt, const IVec2& tex1Size)
    208 		: FboColorbufferCase	(context, name, description, tex0Fmt)
    209 		, m_tex0Fmt				(tex0Fmt)
    210 		, m_tex1Fmt				(tex1Fmt)
    211 		, m_tex0Size			(tex0Size)
    212 		, m_tex1Size			(tex1Size)
    213 	{
    214 	}
    215 
    216 protected:
    217 	void preCheck (void)
    218 	{
    219 		checkFormatSupport(m_tex0Fmt);
    220 		checkFormatSupport(m_tex1Fmt);
    221 	}
    222 
    223 	void render (tcu::Surface& dst)
    224 	{
    225 		tcu::TextureFormat		texFmt0			= glu::mapGLInternalFormat(m_tex0Fmt);
    226 		tcu::TextureFormat		texFmt1			= glu::mapGLInternalFormat(m_tex1Fmt);
    227 		tcu::TextureFormatInfo	fmtInfo0		= tcu::getTextureFormatInfo(texFmt0);
    228 		tcu::TextureFormatInfo	fmtInfo1		= tcu::getTextureFormatInfo(texFmt1);
    229 
    230 		Texture2DShader			texToFbo0Shader	(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt0), fmtInfo0.valueMax-fmtInfo0.valueMin, fmtInfo0.valueMin);
    231 		Texture2DShader			texToFbo1Shader	(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt1), fmtInfo1.valueMax-fmtInfo1.valueMin, fmtInfo1.valueMin);
    232 		Texture2DShader			multiTexShader	(DataTypes() << glu::getSampler2DType(texFmt0) << glu::getSampler2DType(texFmt1), glu::TYPE_FLOAT_VEC4);
    233 
    234 		deUint32				texToFbo0ShaderID = getCurrentContext()->createProgram(&texToFbo0Shader);
    235 		deUint32				texToFbo1ShaderID = getCurrentContext()->createProgram(&texToFbo1Shader);
    236 		deUint32				multiTexShaderID  = getCurrentContext()->createProgram(&multiTexShader);
    237 
    238 		// Setup shaders
    239 		multiTexShader.setTexScaleBias(0, fmtInfo0.lookupScale * 0.5f, fmtInfo0.lookupBias * 0.5f);
    240 		multiTexShader.setTexScaleBias(1, fmtInfo1.lookupScale * 0.5f, fmtInfo1.lookupBias * 0.5f);
    241 		texToFbo0Shader.setUniforms(*getCurrentContext(), texToFbo0ShaderID);
    242 		texToFbo1Shader.setUniforms(*getCurrentContext(), texToFbo1ShaderID);
    243 		multiTexShader.setUniforms (*getCurrentContext(), multiTexShaderID);
    244 
    245 		// Framebuffers.
    246 		deUint32				fbo0, fbo1;
    247 		deUint32				tex0, tex1;
    248 
    249 		for (int ndx = 0; ndx < 2; ndx++)
    250 		{
    251 			glu::TransferFormat		transferFmt		= glu::getTransferFormat(ndx ? texFmt1 : texFmt0);
    252 			deUint32				format			= ndx ? m_tex1Fmt : m_tex0Fmt;
    253 			bool					isFilterable	= glu::isGLInternalColorFormatFilterable(format);
    254 			const IVec2&			size			= ndx ? m_tex1Size : m_tex0Size;
    255 			deUint32&				fbo				= ndx ? fbo1 : fbo0;
    256 			deUint32&				tex				= ndx ? tex1 : tex0;
    257 
    258 			glGenFramebuffers(1, &fbo);
    259 			glGenTextures(1, &tex);
    260 
    261 			glBindTexture(GL_TEXTURE_2D, tex);
    262 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
    263 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
    264 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
    265 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
    266 			glTexImage2D(GL_TEXTURE_2D, 0, format, size.x(), size.y(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
    267 
    268 			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    269 			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
    270 			checkError();
    271 			checkFramebufferStatus(GL_FRAMEBUFFER);
    272 		}
    273 
    274 		// Render textures to both framebuffers.
    275 		for (int ndx = 0; ndx < 2; ndx++)
    276 		{
    277 			const deUint32		format		= GL_RGBA;
    278 			const deUint32		dataType	= GL_UNSIGNED_BYTE;
    279 			const int			texW		= 128;
    280 			const int			texH		= 128;
    281 			deUint32			tmpTex		= 0;
    282 			deUint32			fbo			= ndx ? fbo1 : fbo0;
    283 			const IVec2&		viewport	= ndx ? m_tex1Size : m_tex0Size;
    284 			tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
    285 
    286 			if (ndx == 0)
    287 				tcu::fillWithComponentGradients(data.getAccess(), Vec4(0.0f), Vec4(1.0f));
    288 			else
    289 				tcu::fillWithGrid(data.getAccess(), 8, Vec4(0.2f, 0.7f, 0.1f, 1.0f), Vec4(0.7f, 0.1f, 0.5f, 0.8f));
    290 
    291 			glGenTextures(1, &tmpTex);
    292 			glBindTexture(GL_TEXTURE_2D, tmpTex);
    293 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
    294 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
    295 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_LINEAR);
    296 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_LINEAR);
    297 			glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
    298 
    299 			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    300 			glViewport(0, 0, viewport.x(), viewport.y());
    301 			sglr::drawQuad(*getCurrentContext(), ndx ? texToFbo1ShaderID : texToFbo0ShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    302 		}
    303 
    304 		// Render to framebuffer.
    305 		glBindFramebuffer(GL_FRAMEBUFFER, 0);
    306 		glViewport(0, 0, getWidth(), getHeight());
    307 		glActiveTexture(GL_TEXTURE0);
    308 		glBindTexture(GL_TEXTURE_2D, tex0);
    309 		glActiveTexture(GL_TEXTURE1);
    310 		glBindTexture(GL_TEXTURE_2D, tex1);
    311 		sglr::drawQuad(*getCurrentContext(), multiTexShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    312 
    313 		readPixels(dst, 0, 0, getWidth(), getHeight());
    314 	}
    315 
    316 private:
    317 	deUint32		m_tex0Fmt;
    318 	deUint32		m_tex1Fmt;
    319 	IVec2			m_tex0Size;
    320 	IVec2			m_tex1Size;
    321 };
    322 
    323 class FboColorTexCubeCase : public FboColorbufferCase
    324 {
    325 public:
    326 	FboColorTexCubeCase			(Context& context, const char* name, const char* description, deUint32 texFmt, const IVec2& texSize)
    327 		: FboColorbufferCase	(context, name, description, texFmt)
    328 		, m_texSize				(texSize)
    329 	{
    330 	}
    331 
    332 protected:
    333 	void preCheck (void)
    334 	{
    335 		checkFormatSupport(m_format);
    336 	}
    337 
    338 	void render (tcu::Surface& dst)
    339 	{
    340 		static const deUint32 cubeGLFaces[] =
    341 		{
    342 			GL_TEXTURE_CUBE_MAP_POSITIVE_X,
    343 			GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
    344 			GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
    345 			GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
    346 			GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
    347 			GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
    348 		};
    349 
    350 		static const tcu::CubeFace cubeTexFaces[] =
    351 		{
    352 			tcu::CUBEFACE_POSITIVE_X,
    353 			tcu::CUBEFACE_POSITIVE_Y,
    354 			tcu::CUBEFACE_POSITIVE_Z,
    355 			tcu::CUBEFACE_NEGATIVE_X,
    356 			tcu::CUBEFACE_NEGATIVE_Y,
    357 			tcu::CUBEFACE_NEGATIVE_Z
    358 		};
    359 
    360 		de::Random				rnd					(deStringHash(getName()) ^ 0x9eef603d);
    361 		tcu::TextureFormat		texFmt				= glu::mapGLInternalFormat(m_format);
    362 		tcu::TextureFormatInfo	fmtInfo				= tcu::getTextureFormatInfo(texFmt);
    363 
    364 		Texture2DShader			texToFboShader		(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin);
    365 		TextureCubeShader		cubeTexShader		(glu::getSamplerCubeType(texFmt), glu::TYPE_FLOAT_VEC4);
    366 
    367 		deUint32				texToFboShaderID	= getCurrentContext()->createProgram(&texToFboShader);
    368 		deUint32				cubeTexShaderID		= getCurrentContext()->createProgram(&cubeTexShader);
    369 
    370 		// Setup shaders
    371 		texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
    372 		cubeTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
    373 
    374 		// Framebuffers.
    375 		std::vector<deUint32>	fbos;
    376 		deUint32				tex;
    377 
    378 		{
    379 			glu::TransferFormat		transferFmt		= glu::getTransferFormat(texFmt);
    380 			bool					isFilterable	= glu::isGLInternalColorFormatFilterable(m_format);
    381 			const IVec2&			size			= m_texSize;
    382 
    383 
    384 			glGenTextures(1, &tex);
    385 
    386 			glBindTexture(GL_TEXTURE_CUBE_MAP,		tex);
    387 			glTexParameteri(GL_TEXTURE_CUBE_MAP,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
    388 			glTexParameteri(GL_TEXTURE_CUBE_MAP,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
    389 			glTexParameteri(GL_TEXTURE_CUBE_MAP,	GL_TEXTURE_MIN_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
    390 			glTexParameteri(GL_TEXTURE_CUBE_MAP,	GL_TEXTURE_MAG_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
    391 
    392 			// Generate an image and FBO for each cube face
    393 			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cubeGLFaces); ndx++)
    394 				glTexImage2D(cubeGLFaces[ndx], 0, m_format, size.x(), size.y(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
    395 			checkError();
    396 
    397 			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cubeGLFaces); ndx++)
    398 			{
    399 				deUint32			layerFbo;
    400 
    401 				glGenFramebuffers(1, &layerFbo);
    402 				glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
    403 				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cubeGLFaces[ndx], tex, 0);
    404 				checkError();
    405 				checkFramebufferStatus(GL_FRAMEBUFFER);
    406 
    407 				fbos.push_back(layerFbo);
    408 			}
    409 		}
    410 
    411 		// Render test images to random cube faces
    412 		std::vector<int> order;
    413 
    414 		for (size_t n = 0; n < fbos.size(); n++)
    415 			order.push_back((int)n);
    416 		rnd.shuffle(order.begin(), order.end());
    417 
    418 		DE_ASSERT(order.size() >= 4);
    419 		for (int ndx = 0; ndx < 4; ndx++)
    420 		{
    421 			const int			face		= order[ndx];
    422 			const deUint32		format		= GL_RGBA;
    423 			const deUint32		dataType	= GL_UNSIGNED_BYTE;
    424 			const int			texW		= 128;
    425 			const int			texH		= 128;
    426 			deUint32			tmpTex		= 0;
    427 			const deUint32		fbo			= fbos[face];
    428 			const IVec2&		viewport	= m_texSize;
    429 			tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
    430 
    431 			tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
    432 
    433 			glGenTextures(1, &tmpTex);
    434 			glBindTexture(GL_TEXTURE_2D, tmpTex);
    435 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
    436 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
    437 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_LINEAR);
    438 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_LINEAR);
    439 			glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
    440 
    441 			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    442 			glViewport(0, 0, viewport.x(), viewport.y());
    443 			sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    444 			checkError();
    445 
    446 			// Render to framebuffer
    447 			{
    448 				const Vec3		p0	= Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
    449 				const Vec3		p1	= p0 + Vec3(1.0f, 1.0f, 0.0f);
    450 
    451 				glBindFramebuffer(GL_FRAMEBUFFER, 0);
    452 				glViewport(0, 0, getWidth(), getHeight());
    453 
    454 				glActiveTexture(GL_TEXTURE0);
    455 				glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
    456 
    457 				cubeTexShader.setFace(cubeTexFaces[face]);
    458 				cubeTexShader.setUniforms(*getCurrentContext(), cubeTexShaderID);
    459 
    460 				sglr::drawQuad(*getCurrentContext(), cubeTexShaderID, p0, p1);
    461 				checkError();
    462 			}
    463 		}
    464 
    465 		readPixels(dst, 0, 0, getWidth(), getHeight());
    466 	}
    467 
    468 private:
    469 	IVec2			m_texSize;
    470 };
    471 
    472 class FboColorTex2DArrayCase : public FboColorbufferCase
    473 {
    474 public:
    475 	FboColorTex2DArrayCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec3& texSize)
    476 		: FboColorbufferCase	(context, name, description, texFmt)
    477 		, m_texSize				(texSize)
    478 	{
    479 	}
    480 
    481 protected:
    482 	void preCheck (void)
    483 	{
    484 		checkFormatSupport(m_format);
    485 	}
    486 
    487 	void render (tcu::Surface& dst)
    488 	{
    489 		de::Random				rnd					(deStringHash(getName()) ^ 0xed607a89);
    490 		tcu::TextureFormat		texFmt				= glu::mapGLInternalFormat(m_format);
    491 		tcu::TextureFormatInfo	fmtInfo				= tcu::getTextureFormatInfo(texFmt);
    492 
    493 		Texture2DShader			texToFboShader		(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin);
    494 		Texture2DArrayShader	arrayTexShader		(glu::getSampler2DArrayType(texFmt), glu::TYPE_FLOAT_VEC4);
    495 
    496 		deUint32				texToFboShaderID	= getCurrentContext()->createProgram(&texToFboShader);
    497 		deUint32				arrayTexShaderID	= getCurrentContext()->createProgram(&arrayTexShader);
    498 
    499 		// Setup textures
    500 		texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
    501 		arrayTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
    502 
    503 		// Framebuffers.
    504 		std::vector<deUint32>	fbos;
    505 		deUint32				tex;
    506 
    507 		{
    508 			glu::TransferFormat		transferFmt		= glu::getTransferFormat(texFmt);
    509 			bool					isFilterable	= glu::isGLInternalColorFormatFilterable(m_format);
    510 			const IVec3&			size			= m_texSize;
    511 
    512 
    513 			glGenTextures(1, &tex);
    514 
    515 			glBindTexture(GL_TEXTURE_2D_ARRAY,		tex);
    516 			glTexParameteri(GL_TEXTURE_2D_ARRAY,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
    517 			glTexParameteri(GL_TEXTURE_2D_ARRAY,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
    518 			glTexParameteri(GL_TEXTURE_2D_ARRAY,	GL_TEXTURE_WRAP_R,		GL_CLAMP_TO_EDGE);
    519 			glTexParameteri(GL_TEXTURE_2D_ARRAY,	GL_TEXTURE_MIN_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
    520 			glTexParameteri(GL_TEXTURE_2D_ARRAY,	GL_TEXTURE_MAG_FILTER,	isFilterable ? GL_LINEAR : GL_NEAREST);
    521 			glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, m_format, size.x(), size.y(), size.z(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
    522 
    523 			// Generate an FBO for each layer
    524 			for (int ndx = 0; ndx < m_texSize.z(); ndx++)
    525 			{
    526 				deUint32			layerFbo;
    527 
    528 				glGenFramebuffers(1, &layerFbo);
    529 				glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
    530 				glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, ndx);
    531 				checkError();
    532 				checkFramebufferStatus(GL_FRAMEBUFFER);
    533 
    534 				fbos.push_back(layerFbo);
    535 			}
    536 		}
    537 
    538 		// Render test images to random texture layers
    539 		std::vector<int>		order;
    540 
    541 		for (size_t n = 0; n < fbos.size(); n++)
    542 			order.push_back((int)n);
    543 		rnd.shuffle(order.begin(), order.end());
    544 
    545 		for (size_t ndx = 0; ndx < order.size(); ndx++)
    546 		{
    547 			const int			layer		= order[ndx];
    548 			const deUint32		format		= GL_RGBA;
    549 			const deUint32		dataType	= GL_UNSIGNED_BYTE;
    550 			const int			texW		= 128;
    551 			const int			texH		= 128;
    552 			deUint32			tmpTex		= 0;
    553 			const deUint32		fbo			= fbos[layer];
    554 			const IVec3&		viewport	= m_texSize;
    555 			tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
    556 
    557 			tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
    558 
    559 			glGenTextures(1, &tmpTex);
    560 			glBindTexture(GL_TEXTURE_2D, tmpTex);
    561 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
    562 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
    563 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_LINEAR);
    564 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_LINEAR);
    565 			glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
    566 
    567 			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    568 			glViewport(0, 0, viewport.x(), viewport.y());
    569 			sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    570 			checkError();
    571 
    572 			// Render to framebuffer
    573 			{
    574 				const Vec3		p0	= Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
    575 				const Vec3		p1	= p0 + Vec3(1.0f, 1.0f, 0.0f);
    576 
    577 				glBindFramebuffer(GL_FRAMEBUFFER, 0);
    578 				glViewport(0, 0, getWidth(), getHeight());
    579 
    580 				glActiveTexture(GL_TEXTURE0);
    581 				glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
    582 
    583 				arrayTexShader.setLayer(layer);
    584 				arrayTexShader.setUniforms(*getCurrentContext(), arrayTexShaderID);
    585 
    586 				sglr::drawQuad(*getCurrentContext(), arrayTexShaderID, p0, p1);
    587 				checkError();
    588 			}
    589 		}
    590 
    591 		readPixels(dst, 0, 0, getWidth(), getHeight());
    592 	}
    593 
    594 private:
    595 	IVec3			m_texSize;
    596 };
    597 
    598 class FboColorTex3DCase : public FboColorbufferCase
    599 {
    600 public:
    601 	FboColorTex3DCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec3& texSize)
    602 		: FboColorbufferCase	(context, name, description, texFmt)
    603 		, m_texSize				(texSize)
    604 	{
    605 	}
    606 
    607 protected:
    608 	void preCheck (void)
    609 	{
    610 		checkFormatSupport(m_format);
    611 	}
    612 
    613 	void render (tcu::Surface& dst)
    614 	{
    615 		de::Random				rnd				(deStringHash(getName()) ^ 0x74d947b2);
    616 		tcu::TextureFormat		texFmt			= glu::mapGLInternalFormat(m_format);
    617 		tcu::TextureFormatInfo	fmtInfo			= tcu::getTextureFormatInfo(texFmt);
    618 
    619 		Texture2DShader			texToFboShader	(DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin);
    620 		Texture3DShader			tdTexShader		(glu::getSampler3DType(texFmt), glu::TYPE_FLOAT_VEC4);
    621 
    622 		deUint32				texToFboShaderID= getCurrentContext()->createProgram(&texToFboShader);
    623 		deUint32				tdTexShaderID	= getCurrentContext()->createProgram(&tdTexShader);
    624 
    625 		// Setup shaders
    626 		texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID);
    627 		tdTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias);
    628 
    629 		// Framebuffers.
    630 		std::vector<deUint32>	fbos;
    631 		deUint32				tex;
    632 
    633 		{
    634 			glu::TransferFormat		transferFmt		= glu::getTransferFormat(texFmt);
    635 			const IVec3&			size			= m_texSize;
    636 
    637 			glGenTextures(1, &tex);
    638 
    639 			glBindTexture(GL_TEXTURE_3D,		tex);
    640 			glTexParameteri(GL_TEXTURE_3D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
    641 			glTexParameteri(GL_TEXTURE_3D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
    642 			glTexParameteri(GL_TEXTURE_3D,	GL_TEXTURE_WRAP_R,		GL_CLAMP_TO_EDGE);
    643 			glTexParameteri(GL_TEXTURE_3D,	GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
    644 			glTexParameteri(GL_TEXTURE_3D,	GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
    645 			glTexImage3D(GL_TEXTURE_3D, 0, m_format, size.x(), size.y(), size.z(), 0, transferFmt.format, transferFmt.dataType, DE_NULL);
    646 
    647 			// Generate an FBO for each layer
    648 			for (int ndx = 0; ndx < m_texSize.z(); ndx++)
    649 			{
    650 				deUint32			layerFbo;
    651 
    652 				glGenFramebuffers(1, &layerFbo);
    653 				glBindFramebuffer(GL_FRAMEBUFFER, layerFbo);
    654 				glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, ndx);
    655 				checkError();
    656 				checkFramebufferStatus(GL_FRAMEBUFFER);
    657 
    658 				fbos.push_back(layerFbo);
    659 			}
    660 		}
    661 
    662 		// Render test images to random texture layers
    663 		std::vector<int> order;
    664 
    665 		for (size_t n = 0; n < fbos.size(); n++)
    666 			order.push_back((int)n);
    667 		rnd.shuffle(order.begin(), order.end());
    668 
    669 		for (size_t ndx = 0; ndx < order.size(); ndx++)
    670 		{
    671 			const int			layer		= order[ndx];
    672 			const deUint32		format		= GL_RGBA;
    673 			const deUint32		dataType	= GL_UNSIGNED_BYTE;
    674 			const int			texW		= 128;
    675 			const int			texH		= 128;
    676 			deUint32			tmpTex		= 0;
    677 			const deUint32		fbo			= fbos[layer];
    678 			const IVec3&		viewport	= m_texSize;
    679 			tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
    680 
    681 			tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f));
    682 
    683 			glGenTextures(1, &tmpTex);
    684 			glBindTexture(GL_TEXTURE_2D, tmpTex);
    685 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
    686 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
    687 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_LINEAR);
    688 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_LINEAR);
    689 			glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
    690 
    691 			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    692 			glViewport(0, 0, viewport.x(), viewport.y());
    693 			sglr::drawQuad(*getCurrentContext() , texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    694 			checkError();
    695 
    696 			// Render to framebuffer
    697 			{
    698 				const Vec3		p0	= Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f);
    699 				const Vec3		p1	= p0 + Vec3(1.0f, 1.0f, 0.0f);
    700 
    701 				glBindFramebuffer(GL_FRAMEBUFFER, 0);
    702 				glViewport(0, 0, getWidth(), getHeight());
    703 
    704 				glActiveTexture(GL_TEXTURE0);
    705 				glBindTexture(GL_TEXTURE_3D, tex);
    706 
    707 				tdTexShader.setDepth(float(layer) / float(m_texSize.z()-1));
    708 				tdTexShader.setUniforms(*getCurrentContext(), tdTexShaderID);
    709 
    710 				sglr::drawQuad(*getCurrentContext(), tdTexShaderID, p0, p1);
    711 				checkError();
    712 			}
    713 		}
    714 
    715 		readPixels(dst, 0, 0, getWidth(), getHeight());
    716 	}
    717 
    718 private:
    719 	IVec3			m_texSize;
    720 };
    721 
    722 class FboBlendCase : public FboColorbufferCase
    723 {
    724 public:
    725 	FboBlendCase (Context& context, const char* name, const char* desc, deUint32 format, IVec2 size, deUint32 funcRGB, deUint32 funcAlpha, deUint32 srcRGB, deUint32 dstRGB, deUint32 srcAlpha, deUint32 dstAlpha)
    726 		: FboColorbufferCase	(context, name, desc, format)
    727 		, m_size				(size)
    728 		, m_funcRGB				(funcRGB)
    729 		, m_funcAlpha			(funcAlpha)
    730 		, m_srcRGB				(srcRGB)
    731 		, m_dstRGB				(dstRGB)
    732 		, m_srcAlpha			(srcAlpha)
    733 		, m_dstAlpha			(dstAlpha)
    734 	{
    735 	}
    736 
    737 protected:
    738 	void preCheck (void)
    739 	{
    740 		checkFormatSupport(m_format);
    741 	}
    742 
    743 	void render (tcu::Surface& dst)
    744 	{
    745 		// \note Assumes floating-point or fixed-point format.
    746 		tcu::TextureFormat			fboFmt			= glu::mapGLInternalFormat(m_format);
    747 		Texture2DShader				texShader		(DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4);
    748 		GradientShader				gradShader		(glu::TYPE_FLOAT_VEC4);
    749 		deUint32					texShaderID		= getCurrentContext()->createProgram(&texShader);
    750 		deUint32					gradShaderID	= getCurrentContext()->createProgram(&gradShader);
    751 		deUint32					fbo				= 0;
    752 		deUint32					rbo				= 0;
    753 
    754 		// Setup shaders
    755 		texShader.setUniforms (*getCurrentContext(), texShaderID);
    756 		gradShader.setGradient(*getCurrentContext(), gradShaderID, tcu::Vec4(0.0f), tcu::Vec4(1.0f));
    757 
    758 		glGenFramebuffers(1, &fbo);
    759 		glGenRenderbuffers(1, &rbo);
    760 
    761 		glBindRenderbuffer(GL_RENDERBUFFER, rbo);
    762 		glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_size.x(), m_size.y());
    763 		checkError();
    764 
    765 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    766 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
    767 		checkError();
    768 		checkFramebufferStatus(GL_FRAMEBUFFER);
    769 
    770 		glViewport(0, 0, m_size.x(), m_size.y());
    771 
    772 		// Fill framebuffer with grid pattern.
    773 		{
    774 			const deUint32		format		= GL_RGBA;
    775 			const deUint32		dataType	= GL_UNSIGNED_BYTE;
    776 			const int			texW		= 128;
    777 			const int			texH		= 128;
    778 			deUint32			gridTex		= 0;
    779 			tcu::TextureLevel	data		(glu::mapGLTransferFormat(format, dataType), texW, texH, 1);
    780 
    781 			tcu::fillWithGrid(data.getAccess(), 8, Vec4(0.2f, 0.7f, 0.1f, 1.0f), Vec4(0.7f, 0.1f, 0.5f, 0.8f));
    782 
    783 			glGenTextures(1, &gridTex);
    784 			glBindTexture(GL_TEXTURE_2D, gridTex);
    785 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
    786 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
    787 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MIN_FILTER,	GL_LINEAR);
    788 			glTexParameteri(GL_TEXTURE_2D,	GL_TEXTURE_MAG_FILTER,	GL_LINEAR);
    789 			glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
    790 
    791 			sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    792 		}
    793 
    794 		// Setup blend.
    795 		glEnable(GL_BLEND);
    796 		glBlendEquationSeparate(m_funcRGB, m_funcAlpha);
    797 		glBlendFuncSeparate(m_srcRGB, m_dstRGB, m_srcAlpha, m_dstAlpha);
    798 
    799 		// Render gradient with blend.
    800 		sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f));
    801 
    802 		readPixels(dst, 0, 0, m_size.x(), m_size.y(), fboFmt, Vec4(1.0f), Vec4(0.0f));
    803 	}
    804 
    805 private:
    806 	IVec2		m_size;
    807 	deUint32	m_funcRGB;
    808 	deUint32	m_funcAlpha;
    809 	deUint32	m_srcRGB;
    810 	deUint32	m_dstRGB;
    811 	deUint32	m_srcAlpha;
    812 	deUint32	m_dstAlpha;
    813 };
    814 
    815 FboColorTests::FboColorTests (Context& context)
    816 	: TestCaseGroup(context, "color", "Colorbuffer tests")
    817 {
    818 }
    819 
    820 FboColorTests::~FboColorTests (void)
    821 {
    822 }
    823 
    824 void FboColorTests::init (void)
    825 {
    826 	static const deUint32 colorFormats[] =
    827 	{
    828 		// RGBA formats
    829 		GL_RGBA32I,
    830 		GL_RGBA32UI,
    831 		GL_RGBA16I,
    832 		GL_RGBA16UI,
    833 		GL_RGBA8,
    834 		GL_RGBA8I,
    835 		GL_RGBA8UI,
    836 		GL_SRGB8_ALPHA8,
    837 		GL_RGB10_A2,
    838 		GL_RGB10_A2UI,
    839 		GL_RGBA4,
    840 		GL_RGB5_A1,
    841 
    842 		// RGB formats
    843 		GL_RGB8,
    844 		GL_RGB565,
    845 
    846 		// RG formats
    847 		GL_RG32I,
    848 		GL_RG32UI,
    849 		GL_RG16I,
    850 		GL_RG16UI,
    851 		GL_RG8,
    852 		GL_RG8I,
    853 		GL_RG8UI,
    854 
    855 		// R formats
    856 		GL_R32I,
    857 		GL_R32UI,
    858 		GL_R16I,
    859 		GL_R16UI,
    860 		GL_R8,
    861 		GL_R8I,
    862 		GL_R8UI,
    863 
    864 		// GL_EXT_color_buffer_float
    865 		GL_RGBA32F,
    866 		GL_RGBA16F,
    867 		GL_R11F_G11F_B10F,
    868 		GL_RG32F,
    869 		GL_RG16F,
    870 		GL_R32F,
    871 		GL_R16F,
    872 
    873 		// GL_EXT_color_buffer_half_float
    874 		GL_RGB16F
    875 	};
    876 
    877 	// .clear
    878 	{
    879 		tcu::TestCaseGroup* clearGroup = new tcu::TestCaseGroup(m_testCtx, "clear", "Color clears");
    880 		addChild(clearGroup);
    881 
    882 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++)
    883 			clearGroup->addChild(new FboColorClearCase(m_context, getFormatName(colorFormats[ndx]), "", colorFormats[ndx], 129, 117));
    884 	}
    885 
    886 	// .tex2d
    887 	{
    888 		tcu::TestCaseGroup* tex2DGroup = new tcu::TestCaseGroup(m_testCtx, "tex2d", "Texture 2D tests");
    889 		addChild(tex2DGroup);
    890 
    891 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
    892 			tex2DGroup->addChild(new FboColorMultiTex2DCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
    893 															colorFormats[fmtNdx], IVec2(129, 117),
    894 															colorFormats[fmtNdx], IVec2(99, 128)));
    895 	}
    896 
    897 	// .texcube
    898 	{
    899 		tcu::TestCaseGroup* texCubeGroup = new tcu::TestCaseGroup(m_testCtx, "texcube", "Texture cube map tests");
    900 		addChild(texCubeGroup);
    901 
    902 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
    903 			texCubeGroup->addChild(new FboColorTexCubeCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
    904 														   colorFormats[fmtNdx], IVec2(128, 128)));
    905 	}
    906 
    907 	// .tex2darray
    908 	{
    909 		tcu::TestCaseGroup* tex2DArrayGroup = new tcu::TestCaseGroup(m_testCtx, "tex2darray", "Texture 2D array tests");
    910 		addChild(tex2DArrayGroup);
    911 
    912 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
    913 			tex2DArrayGroup->addChild(new FboColorTex2DArrayCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
    914 																 colorFormats[fmtNdx], IVec3(128, 128, 5)));
    915 	}
    916 
    917 	// .tex3d
    918 	{
    919 		tcu::TestCaseGroup* tex3DGroup = new tcu::TestCaseGroup(m_testCtx, "tex3d", "Texture 3D tests");
    920 		addChild(tex3DGroup);
    921 
    922 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
    923 			tex3DGroup->addChild(new FboColorTex3DCase(m_context, getFormatName(colorFormats[fmtNdx]), "",
    924 													   colorFormats[fmtNdx], IVec3(128, 128, 5)));
    925 	}
    926 
    927 	// .blend
    928 	{
    929 		tcu::TestCaseGroup* blendGroup = new tcu::TestCaseGroup(m_testCtx, "blend", "Blending tests");
    930 		addChild(blendGroup);
    931 
    932 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++)
    933 		{
    934 			deUint32					format		= colorFormats[fmtNdx];
    935 			tcu::TextureFormat			texFmt		= glu::mapGLInternalFormat(format);
    936 			tcu::TextureChannelClass	fmtClass	= tcu::getTextureChannelClass(texFmt.type);
    937 			string						fmtName		= getFormatName(format);
    938 
    939 			if (texFmt.type	== tcu::TextureFormat::FLOAT				||
    940 				fmtClass	== tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER	||
    941 				fmtClass	== tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
    942 				continue; // Blending is not supported.
    943 
    944 			blendGroup->addChild(new FboBlendCase(m_context, (fmtName + "_src_over").c_str(), "", format, IVec2(127, 111), GL_FUNC_ADD, GL_FUNC_ADD, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE));
    945 		}
    946 	}
    947 }
    948 
    949 } // Functional
    950 } // gles3
    951 } // deqp
    952