Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.1 Module
      3  * -------------------------------------------------
      4  *
      5  * Copyright 2015 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 border clamp tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fTextureBorderClampTests.hpp"
     25 
     26 #include "glsTextureTestUtil.hpp"
     27 
     28 #include "tcuTextureUtil.hpp"
     29 #include "tcuTexLookupVerifier.hpp"
     30 #include "tcuTexCompareVerifier.hpp"
     31 #include "tcuCompressedTexture.hpp"
     32 #include "tcuResultCollector.hpp"
     33 #include "tcuSurface.hpp"
     34 #include "tcuSeedBuilder.hpp"
     35 #include "tcuVectorUtil.hpp"
     36 
     37 #include "rrGenericVector.hpp"
     38 
     39 #include "gluContextInfo.hpp"
     40 #include "gluTexture.hpp"
     41 #include "gluTextureUtil.hpp"
     42 #include "gluPixelTransfer.hpp"
     43 #include "gluStrUtil.hpp"
     44 #include "gluObjectWrapper.hpp"
     45 #include "gluShaderProgram.hpp"
     46 #include "gluDrawUtil.hpp"
     47 
     48 #include "glwEnums.hpp"
     49 #include "glwFunctions.hpp"
     50 
     51 #include "deStringUtil.hpp"
     52 #include "deUniquePtr.hpp"
     53 #include "deRandom.hpp"
     54 
     55 #include <limits>
     56 
     57 
     58 namespace deqp
     59 {
     60 namespace gles31
     61 {
     62 namespace Functional
     63 {
     64 namespace
     65 {
     66 
     67 enum SizeType
     68 {
     69 	SIZE_POT = 0,
     70 	SIZE_NPOT
     71 };
     72 
     73 bool filterRequiresFilterability (deUint32 filter)
     74 {
     75 	switch (filter)
     76 	{
     77 		case GL_NEAREST:
     78 		case GL_NEAREST_MIPMAP_NEAREST:
     79 			return false;
     80 
     81 		case GL_LINEAR:
     82 		case GL_LINEAR_MIPMAP_NEAREST:
     83 		case GL_NEAREST_MIPMAP_LINEAR:
     84 		case GL_LINEAR_MIPMAP_LINEAR:
     85 			return true;
     86 
     87 		default:
     88 			DE_ASSERT(false);
     89 			return false;
     90 	}
     91 }
     92 
     93 bool isDepthFormat (deUint32 format, tcu::Sampler::DepthStencilMode mode)
     94 {
     95 	if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA || format == GL_ALPHA || format == GL_BGRA)
     96 	{
     97 		// Unsized formats are a special case
     98 		return false;
     99 	}
    100 	else if (glu::isCompressedFormat(format))
    101 	{
    102 		// no known compressed depth formats
    103 		return false;
    104 	}
    105 	else
    106 	{
    107 		const tcu::TextureFormat fmt = glu::mapGLInternalFormat(format);
    108 
    109 		if (fmt.order == tcu::TextureFormat::D)
    110 		{
    111 			DE_ASSERT(mode == tcu::Sampler::MODE_DEPTH);
    112 			return true;
    113 		}
    114 		else if (fmt.order == tcu::TextureFormat::DS && mode == tcu::Sampler::MODE_DEPTH)
    115 			return true;
    116 		else
    117 			return false;
    118 	}
    119 }
    120 
    121 bool isStencilFormat (deUint32 format, tcu::Sampler::DepthStencilMode mode)
    122 {
    123 	if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA || format == GL_ALPHA || format == GL_BGRA)
    124 	{
    125 		// Unsized formats are a special case
    126 		return false;
    127 	}
    128 	else if (glu::isCompressedFormat(format))
    129 	{
    130 		// no known compressed stencil formats
    131 		return false;
    132 	}
    133 	else
    134 	{
    135 		const tcu::TextureFormat fmt = glu::mapGLInternalFormat(format);
    136 
    137 		if (fmt.order == tcu::TextureFormat::S)
    138 		{
    139 			DE_ASSERT(mode == tcu::Sampler::MODE_STENCIL);
    140 			return true;
    141 		}
    142 		else if (fmt.order == tcu::TextureFormat::DS && mode == tcu::Sampler::MODE_STENCIL)
    143 			return true;
    144 		else
    145 			return false;
    146 	}
    147 }
    148 
    149 tcu::TextureChannelClass getFormatChannelClass (deUint32 format, tcu::Sampler::DepthStencilMode mode)
    150 {
    151 	if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA || format == GL_ALPHA || format == GL_BGRA)
    152 	{
    153 		// Unsized formats are a special c, use UNORM8
    154 		return tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
    155 	}
    156 	else if (glu::isCompressedFormat(format))
    157 	{
    158 		const tcu::CompressedTexFormat	compressedFmt	= glu::mapGLCompressedTexFormat(format);
    159 		const tcu::TextureFormat		uncompressedFmt	= tcu::getUncompressedFormat(compressedFmt);
    160 		return tcu::getTextureChannelClass(uncompressedFmt.type);
    161 	}
    162 	else
    163 	{
    164 		const tcu::TextureFormat fmt			= glu::mapGLInternalFormat(format);
    165 		const tcu::TextureFormat effectiveFmt	= tcu::getEffectiveDepthStencilTextureFormat(fmt, mode);
    166 
    167 		return tcu::getTextureChannelClass(effectiveFmt.type);
    168 	}
    169 }
    170 
    171 int getDimensionNumBlocks (int dimensionSize, int blockSize)
    172 {
    173 	// ceil( a / b )
    174 	return (dimensionSize + blockSize - 1) / blockSize;
    175 }
    176 
    177 void generateDummyCompressedData (tcu::CompressedTexture& dst, const tcu::CompressedTexFormat& format)
    178 {
    179 	const int			blockByteSize	= tcu::getBlockSize(format);
    180 	const tcu::IVec3	blockPixelSize	= tcu::getBlockPixelSize(format);
    181 	const tcu::IVec3	numBlocks		(getDimensionNumBlocks(dst.getWidth(),    blockPixelSize.x()),
    182 										 getDimensionNumBlocks(dst.getHeight(),   blockPixelSize.y()),
    183 										 getDimensionNumBlocks(dst.getDepth(),    blockPixelSize.z()));
    184 	const int			numTotalBlocks	= numBlocks.x() * numBlocks.y() * numBlocks.z();
    185 	const int			dataSize		= numTotalBlocks * blockByteSize;
    186 
    187 	DE_ASSERT(dst.getDataSize() == dataSize);
    188 
    189 	if (tcu::isAstcFormat(format))
    190 	{
    191 		// generate data that is valid in LDR mode
    192 		const int		BLOCK_SIZE			= 16;
    193 		const deUint8	block[BLOCK_SIZE]	= { 252, 253, 255, 255, 255, 255, 255, 255, 223, 251, 28, 206, 54, 251, 160, 174 };
    194 
    195 		DE_ASSERT(blockByteSize == BLOCK_SIZE);
    196 		for (int ndx = 0; ndx < numTotalBlocks; ++ndx)
    197 			deMemcpy((deUint8*)dst.getData() + ndx * BLOCK_SIZE, block, BLOCK_SIZE);
    198 	}
    199 	else
    200 	{
    201 		// any data is ok
    202 		de::Random rnd(0xabc);
    203 
    204 		for (int ndx = 0; ndx < dataSize; ++ndx)
    205 			((deUint8*)dst.getData())[ndx] = rnd.getUint8();
    206 	}
    207 }
    208 
    209 template <typename T>
    210 struct TextureTraits
    211 {
    212 };
    213 
    214 template <>
    215 struct TextureTraits<glu::Texture2D>
    216 {
    217 	typedef tcu::IVec2 SizeType;
    218 
    219 	static de::MovePtr<glu::Texture2D> createTextureFromInternalFormat (glu::RenderContext& renderCtx, deUint32 texFormat, const tcu::IVec2& size)
    220 	{
    221 		return de::MovePtr<glu::Texture2D>(new glu::Texture2D(renderCtx, texFormat, size.x(), size.y()));
    222 	}
    223 
    224 	static de::MovePtr<glu::Texture2D> createTextureFromFormatAndType (glu::RenderContext& renderCtx, deUint32 texFormat, deUint32 type, const tcu::IVec2& size)
    225 	{
    226 		return de::MovePtr<glu::Texture2D>(new glu::Texture2D(renderCtx, texFormat, type, size.x(), size.y()));
    227 	}
    228 
    229 	static de::MovePtr<glu::Texture2D> createTextureFromCompressedData (glu::RenderContext&					renderCtx,
    230 																		const glu::ContextInfo&				ctxInfo,
    231 																		const tcu::CompressedTexture&		compressedLevel,
    232 																		const tcu::TexDecompressionParams&	decompressionParams)
    233 	{
    234 		return de::MovePtr<glu::Texture2D>(new glu::Texture2D(renderCtx,
    235 															  ctxInfo,
    236 															  1,
    237 															  &compressedLevel,
    238 															  decompressionParams));
    239 	}
    240 
    241 	static int getTextureNumLayers (const tcu::IVec2& size)
    242 	{
    243 		// 2D textures have one layer
    244 		DE_UNREF(size);
    245 		return 1;
    246 	}
    247 };
    248 
    249 template <>
    250 struct TextureTraits<glu::Texture3D>
    251 {
    252 	typedef tcu::IVec3 SizeType;
    253 
    254 	static de::MovePtr<glu::Texture3D> createTextureFromInternalFormat (glu::RenderContext& renderCtx, deUint32 texFormat, const tcu::IVec3& size)
    255 	{
    256 		return de::MovePtr<glu::Texture3D>(new glu::Texture3D(renderCtx, texFormat, size.x(), size.y(), size.z()));
    257 	}
    258 
    259 	static de::MovePtr<glu::Texture3D> createTextureFromFormatAndType (glu::RenderContext& renderCtx, deUint32 texFormat, deUint32 type, const tcu::IVec3& size)
    260 	{
    261 		return de::MovePtr<glu::Texture3D>(new glu::Texture3D(renderCtx, texFormat, type, size.x(), size.y(), size.z()));
    262 	}
    263 
    264 	static de::MovePtr<glu::Texture3D> createTextureFromCompressedData (glu::RenderContext&					renderCtx,
    265 																		const glu::ContextInfo&				ctxInfo,
    266 																		const tcu::CompressedTexture&		compressedLevel,
    267 																		const tcu::TexDecompressionParams&	decompressionParams)
    268 	{
    269 		return de::MovePtr<glu::Texture3D>(new glu::Texture3D(renderCtx,
    270 															  ctxInfo,
    271 															  1,
    272 															  &compressedLevel,
    273 															  decompressionParams));
    274 	}
    275 
    276 	static int getTextureNumLayers (const tcu::IVec3& size)
    277 	{
    278 		// 3D textures have Z layers
    279 		return size.z();
    280 	}
    281 };
    282 
    283 template <typename T>
    284 de::MovePtr<T> genDummyTexture (glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, deUint32 texFormat, const typename TextureTraits<T>::SizeType& size)
    285 {
    286 	de::MovePtr<T> texture;
    287 
    288 	if (isDepthFormat(texFormat, tcu::Sampler::MODE_DEPTH) || isStencilFormat(texFormat, tcu::Sampler::MODE_STENCIL))
    289 	{
    290 		// fill different channels with different gradients
    291 		texture = TextureTraits<T>::createTextureFromInternalFormat(renderCtx, texFormat, size);
    292 		texture->getRefTexture().allocLevel(0);
    293 
    294 		if (isDepthFormat(texFormat, tcu::Sampler::MODE_DEPTH))
    295 		{
    296 			// fill depth with 0 -> 1
    297 			const tcu::PixelBufferAccess depthAccess = tcu::getEffectiveDepthStencilAccess(texture->getRefTexture().getLevel(0), tcu::Sampler::MODE_DEPTH);
    298 			tcu::fillWithComponentGradients(depthAccess, tcu::Vec4(0.0f), tcu::Vec4(1.0f));
    299 		}
    300 
    301 		if (isStencilFormat(texFormat, tcu::Sampler::MODE_STENCIL))
    302 		{
    303 			// fill stencil with 0 -> max
    304 			const tcu::PixelBufferAccess	stencilAccess	= tcu::getEffectiveDepthStencilAccess(texture->getRefTexture().getLevel(0), tcu::Sampler::MODE_STENCIL);
    305 			const tcu::TextureFormatInfo	texFormatInfo	= tcu::getTextureFormatInfo(stencilAccess.getFormat());
    306 
    307 			// Flip y to make stencil and depth cases not look identical
    308 			tcu::fillWithComponentGradients(tcu::flipYAccess(stencilAccess), texFormatInfo.valueMax, texFormatInfo.valueMin);
    309 		}
    310 
    311 		texture->upload();
    312 	}
    313 	else if (!glu::isCompressedFormat(texFormat))
    314 	{
    315 		if (texFormat == GL_LUMINANCE || texFormat == GL_LUMINANCE_ALPHA || texFormat == GL_ALPHA || texFormat == GL_BGRA)
    316 			texture = TextureTraits<T>::createTextureFromFormatAndType(renderCtx, texFormat, GL_UNSIGNED_BYTE, size);
    317 		else
    318 			texture = TextureTraits<T>::createTextureFromInternalFormat(renderCtx, texFormat, size);
    319 
    320 		// Fill level 0.
    321 		texture->getRefTexture().allocLevel(0);
    322 
    323 		// fill with gradient min -> max
    324 		{
    325 			const tcu::TextureFormatInfo	texFormatInfo	= tcu::getTextureFormatInfo(texture->getRefTexture().getFormat());
    326 			const tcu::Vec4					rampLow			= texFormatInfo.valueMin;
    327 			const tcu::Vec4					rampHigh		= texFormatInfo.valueMax;
    328 			tcu::fillWithComponentGradients(texture->getRefTexture().getLevel(0), rampLow, rampHigh);
    329 		}
    330 
    331 		texture->upload();
    332 	}
    333 	else
    334 	{
    335 		const tcu::CompressedTexFormat	compressedFormat	= glu::mapGLCompressedTexFormat(texFormat);
    336 		const int						numLayers			= TextureTraits<T>::getTextureNumLayers(size);
    337 		tcu::CompressedTexture			compressedLevel		(compressedFormat, size.x(), size.y(), numLayers);
    338 		const bool						isAstcFormat		= tcu::isAstcFormat(compressedFormat);
    339 		tcu::TexDecompressionParams		decompressionParams	((isAstcFormat) ? (tcu::TexDecompressionParams::ASTCMODE_LDR) : (tcu::TexDecompressionParams::ASTCMODE_LAST));
    340 
    341 		generateDummyCompressedData(compressedLevel, compressedFormat);
    342 
    343 		texture = TextureTraits<T>::createTextureFromCompressedData(renderCtx,
    344 																	ctxInfo,
    345 																	compressedLevel,
    346 																	decompressionParams);
    347 	}
    348 
    349 	return texture;
    350 }
    351 
    352 int getNBitIntegerMaxValue (bool isSigned, int numBits)
    353 {
    354 	DE_ASSERT(numBits < 32);
    355 
    356 	if (numBits == 0)
    357 		return 0;
    358 	else if (isSigned)
    359 		return deIntMaxValue32(numBits);
    360 	else
    361 		return deUintMaxValue32(numBits);
    362 }
    363 
    364 int getNBitIntegerMinValue (bool isSigned, int numBits)
    365 {
    366 	DE_ASSERT(numBits < 32);
    367 
    368 	if (numBits == 0)
    369 		return 0;
    370 	else if (isSigned)
    371 		return deIntMinValue32(numBits);
    372 	else
    373 		return 0;
    374 }
    375 
    376 tcu::IVec4 getNBitIntegerVec4MaxValue (bool isSigned, const tcu::IVec4& numBits)
    377 {
    378 	return tcu::IVec4(getNBitIntegerMaxValue(isSigned, numBits[0]),
    379 					  getNBitIntegerMaxValue(isSigned, numBits[1]),
    380 					  getNBitIntegerMaxValue(isSigned, numBits[2]),
    381 					  getNBitIntegerMaxValue(isSigned, numBits[3]));
    382 }
    383 
    384 tcu::IVec4 getNBitIntegerVec4MinValue (bool isSigned, const tcu::IVec4& numBits)
    385 {
    386 	return tcu::IVec4(getNBitIntegerMinValue(isSigned, numBits[0]),
    387 					  getNBitIntegerMinValue(isSigned, numBits[1]),
    388 					  getNBitIntegerMinValue(isSigned, numBits[2]),
    389 					  getNBitIntegerMinValue(isSigned, numBits[3]));
    390 }
    391 
    392 rr::GenericVec4 mapToFormatColorUnits (const tcu::TextureFormat& texFormat, const tcu::Vec4& normalizedRange)
    393 {
    394 	const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(texFormat);
    395 
    396 	switch (tcu::getTextureChannelClass(texFormat.type))
    397 	{
    398 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:		return rr::GenericVec4(normalizedRange);
    399 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:		return rr::GenericVec4(normalizedRange * 2.0f - 1.0f);
    400 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:			return rr::GenericVec4(texFormatInfo.valueMin + normalizedRange * texFormatInfo.valueMax);
    401 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:			return rr::GenericVec4(tcu::mix(texFormatInfo.valueMin, texFormatInfo.valueMax, normalizedRange).cast<deInt32>());
    402 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:			return rr::GenericVec4(tcu::mix(texFormatInfo.valueMin, texFormatInfo.valueMax, normalizedRange).cast<deUint32>());
    403 
    404 		default:
    405 			DE_ASSERT(false);
    406 			return rr::GenericVec4();
    407 	}
    408 }
    409 
    410 rr::GenericVec4 mapToFormatColorRepresentable (const tcu::TextureFormat& texFormat, const tcu::Vec4& normalizedRange)
    411 {
    412 	// make sure value is representable in the target format and clear channels
    413 	// not present in the target format.
    414 
    415 	const rr::GenericVec4		inFormatUnits	= mapToFormatColorUnits(texFormat, normalizedRange);
    416 	const tcu::BVec4			channelMask		= tcu::getTextureFormatChannelMask(texFormat);
    417 	de::ArrayBuffer<deUint8, 4>	buffer			(texFormat.getPixelSize());
    418 	tcu::PixelBufferAccess		access			(texFormat, tcu::IVec3(1, 1, 1), buffer.getPtr());
    419 
    420 	if (tcu::isSRGB(texFormat))
    421 	{
    422 		DE_ASSERT(texFormat.type == tcu::TextureFormat::UNORM_INT8);
    423 
    424 		// make sure border color (in linear space) can be converted to 8-bit sRGB space without
    425 		// significant loss.
    426 		const tcu::Vec4		sRGB		= tcu::linearToSRGB(normalizedRange);
    427 		const tcu::IVec4	sRGB8		= tcu::IVec4(tcu::floatToU8(sRGB[0]),
    428 													 tcu::floatToU8(sRGB[1]),
    429 													 tcu::floatToU8(sRGB[2]),
    430 													 tcu::floatToU8(sRGB[3]));
    431 		const tcu::Vec4		linearized	= tcu::sRGBToLinear(tcu::Vec4((float)sRGB8[0] / 255.0f,
    432 																	  (float)sRGB8[1] / 255.0f,
    433 																	  (float)sRGB8[2] / 255.0f,
    434 																	  (float)sRGB8[3] / 255.0f));
    435 
    436 		return rr::GenericVec4(tcu::select(linearized, tcu::Vec4(0.0f), channelMask));
    437 	}
    438 
    439 	switch (tcu::getTextureChannelClass(texFormat.type))
    440 	{
    441 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
    442 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
    443 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
    444 		{
    445 			access.setPixel(inFormatUnits.get<float>(), 0, 0);
    446 			return rr::GenericVec4(tcu::select(access.getPixel(0, 0), tcu::Vec4(0.0f), channelMask));
    447 		}
    448 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
    449 		{
    450 			access.setPixel(inFormatUnits.get<deInt32>(), 0, 0);
    451 			return rr::GenericVec4(tcu::select(access.getPixelInt(0, 0), tcu::IVec4(0), channelMask));
    452 		}
    453 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
    454 		{
    455 			access.setPixel(inFormatUnits.get<deUint32>(), 0, 0);
    456 			return rr::GenericVec4(tcu::select(access.getPixelUint(0, 0), tcu::UVec4(0u), channelMask));
    457 		}
    458 		default:
    459 		{
    460 			DE_ASSERT(false);
    461 			return rr::GenericVec4();
    462 		}
    463 	}
    464 }
    465 
    466 bool isCoreFilterableFormat (deUint32 format, tcu::Sampler::DepthStencilMode mode)
    467 {
    468 	const bool	isLuminanceOrAlpha		= (format == GL_LUMINANCE || format == GL_ALPHA || format == GL_LUMINANCE_ALPHA); // special case for luminance/alpha
    469 	const bool	isUnsizedColorFormat	= (format == GL_BGRA);
    470 	const bool	isCompressed			= glu::isCompressedFormat(format);
    471 	const bool	isDepth					= isDepthFormat(format, mode);
    472 	const bool	isStencil				= isStencilFormat(format, mode);
    473 
    474 	// special cases
    475 	if (isLuminanceOrAlpha || isUnsizedColorFormat || isCompressed)
    476 		return true;
    477 	if (isStencil || isDepth)
    478 		return false;
    479 
    480 	// color case
    481 	return glu::isGLInternalColorFormatFilterable(format);
    482 }
    483 
    484 class TextureBorderClampTest : public TestCase
    485 {
    486 public:
    487 	enum StateType
    488 	{
    489 		STATE_SAMPLER_PARAM = 0,
    490 		STATE_TEXTURE_PARAM,
    491 
    492 		STATE_LAST
    493 	};
    494 
    495 	enum SamplingFunction
    496 	{
    497 		SAMPLE_FILTER = 0,
    498 		SAMPLE_GATHER,
    499 
    500 		SAMPLE_LAST
    501 	};
    502 
    503 	enum Flag
    504 	{
    505 		FLAG_USE_SHADOW_SAMPLER = (1u << 0),
    506 	};
    507 
    508 	struct IterationConfig
    509 	{
    510 		tcu::Vec2		p0;
    511 		tcu::Vec2		p1;
    512 		rr::GenericVec4	borderColor;
    513 		tcu::Vec4		lookupScale;
    514 		tcu::Vec4		lookupBias;
    515 		deUint32		minFilter;
    516 		deUint32		magFilter;
    517 		std::string		description;
    518 		deUint32		sWrapMode;
    519 		deUint32		tWrapMode;
    520 		deUint32		compareMode;
    521 		float			compareRef;
    522 	};
    523 
    524 														TextureBorderClampTest		(Context&						context,
    525 																					 const char*					name,
    526 																					 const char*					description,
    527 																					 deUint32						texFormat,
    528 																					 tcu::Sampler::DepthStencilMode	mode,
    529 																					 StateType						stateType,
    530 																					 int							texWidth,
    531 																					 int							texHeight,
    532 																					 SamplingFunction				samplingFunction,
    533 																					 deUint32						flags				= 0);
    534 														~TextureBorderClampTest		(void);
    535 
    536 protected:
    537 	void												init						(void);
    538 	void												deinit						(void);
    539 
    540 private:
    541 	IterateResult										iterate						(void);
    542 
    543 	void												logParams					(const IterationConfig&							config,
    544 																					 const glu::TextureTestUtil::ReferenceParams&	samplerParams);
    545 
    546 	void												renderTo					(tcu::Surface&									surface,
    547 																					 const IterationConfig&							config,
    548 																					 const glu::TextureTestUtil::ReferenceParams&	samplerParams);
    549 	void												renderQuad					(const float*									texCoord,
    550 																					 const glu::TextureTestUtil::ReferenceParams&	samplerParams);
    551 
    552 	void												verifyImage					(const tcu::Surface&							image,
    553 																					 const IterationConfig&							config,
    554 																					 const glu::TextureTestUtil::ReferenceParams&	samplerParams);
    555 
    556 	bool												verifyTextureSampleResult	(const tcu::ConstPixelBufferAccess&				renderedFrame,
    557 																					 const float*									texCoord,
    558 																					 const glu::TextureTestUtil::ReferenceParams&	samplerParams,
    559 																					 const tcu::LodPrecision&						lodPrecision,
    560 																					 const tcu::LookupPrecision&					lookupPrecision);
    561 
    562 	bool												verifyTextureCompareResult	(const tcu::ConstPixelBufferAccess&				renderedFrame,
    563 																					 const float*									texCoord,
    564 																					 const glu::TextureTestUtil::ReferenceParams&	samplerParams,
    565 																					 const tcu::TexComparePrecision&				texComparePrecision,
    566 																					 const tcu::TexComparePrecision&				lowQualityTexComparePrecision,
    567 																					 const tcu::LodPrecision&						lodPrecision,
    568 																					 const tcu::LodPrecision&						lowQualityLodPrecision);
    569 
    570 	bool												verifyTextureGatherResult	(const tcu::ConstPixelBufferAccess&				renderedFrame,
    571 																					 const float*									texCoord,
    572 																					 const glu::TextureTestUtil::ReferenceParams&	samplerParams,
    573 																					 const tcu::LookupPrecision&					lookupPrecision);
    574 
    575 	bool												verifyTextureGatherCmpResult(const tcu::ConstPixelBufferAccess&				renderedFrame,
    576 																					 const float*									texCoord,
    577 																					 const glu::TextureTestUtil::ReferenceParams&	samplerParams,
    578 																					 const tcu::TexComparePrecision&				texComparePrecision,
    579 																					 const tcu::TexComparePrecision&				lowQualityTexComparePrecision);
    580 
    581 	deUint32											getIterationSeed			(const IterationConfig& config) const;
    582 	glu::TextureTestUtil::ReferenceParams				genSamplerParams			(const IterationConfig& config) const;
    583 	glu::ShaderProgram*									genGatherProgram			(void) const;
    584 
    585 	virtual int											getNumIterations			(void) const = 0;
    586 	virtual IterationConfig								getIteration				(int ndx) const = 0;
    587 
    588 protected:
    589 	const glu::Texture2D*								getTexture						(void) const;
    590 
    591 	const deUint32										m_texFormat;
    592 	const tcu::Sampler::DepthStencilMode				m_sampleMode;
    593 	const tcu::TextureChannelClass						m_channelClass;
    594 	const StateType										m_stateType;
    595 
    596 	const int											m_texHeight;
    597 	const int											m_texWidth;
    598 
    599 	const SamplingFunction								m_samplingFunction;
    600 	const bool											m_useShadowSampler;
    601 private:
    602 	enum
    603 	{
    604 		VIEWPORT_WIDTH		= 128,
    605 		VIEWPORT_HEIGHT		= 128,
    606 	};
    607 
    608 	de::MovePtr<glu::Texture2D>							m_texture;
    609 	de::MovePtr<gls::TextureTestUtil::TextureRenderer>	m_renderer;
    610 	de::MovePtr<glu::ShaderProgram>						m_gatherProgram;
    611 
    612 	int													m_iterationNdx;
    613 	tcu::ResultCollector								m_result;
    614 };
    615 
    616 TextureBorderClampTest::TextureBorderClampTest (Context&						context,
    617 												const char*						name,
    618 												const char*						description,
    619 												deUint32						texFormat,
    620 												tcu::Sampler::DepthStencilMode	mode,
    621 												StateType						stateType,
    622 												int								texWidth,
    623 												int								texHeight,
    624 												SamplingFunction				samplingFunction,
    625 												deUint32						flags)
    626 	: TestCase				(context, name, description)
    627 	, m_texFormat			(texFormat)
    628 	, m_sampleMode			(mode)
    629 	, m_channelClass		(getFormatChannelClass(texFormat, mode))
    630 	, m_stateType			(stateType)
    631 	, m_texHeight			(texHeight)
    632 	, m_texWidth			(texWidth)
    633 	, m_samplingFunction	(samplingFunction)
    634 	, m_useShadowSampler	((flags & FLAG_USE_SHADOW_SAMPLER) != 0)
    635 	, m_iterationNdx		(0)
    636 	, m_result				(context.getTestContext().getLog())
    637 {
    638 	DE_ASSERT(stateType < STATE_LAST);
    639 	DE_ASSERT(samplingFunction < SAMPLE_LAST);
    640 	// mode must be set for combined depth-stencil formats
    641 	DE_ASSERT(m_channelClass != tcu::TEXTURECHANNELCLASS_LAST || mode != tcu::Sampler::MODE_LAST);
    642 }
    643 
    644 TextureBorderClampTest::~TextureBorderClampTest (void)
    645 {
    646 	deinit();
    647 }
    648 
    649 void TextureBorderClampTest::init (void)
    650 {
    651 	// requirements
    652 	const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
    653 
    654 	if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_border_clamp"))
    655 		throw tcu::NotSupportedError("Test requires GL_EXT_texture_border_clamp extension");
    656 
    657 	if (glu::isCompressedFormat(m_texFormat)													&&
    658 		!supportsES32																			&&
    659 		tcu::isAstcFormat(glu::mapGLCompressedTexFormat(m_texFormat))							&&
    660 		!m_context.getContextInfo().isExtensionSupported("GL_KHR_texture_compression_astc_ldr"))
    661 	{
    662 		throw tcu::NotSupportedError("Test requires GL_KHR_texture_compression_astc_ldr extension");
    663 	}
    664 
    665 	if (m_texFormat == GL_BGRA && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_format_BGRA8888"))
    666 		throw tcu::NotSupportedError("Test requires GL_EXT_texture_format_BGRA8888 extension");
    667 
    668 	if (m_context.getRenderTarget().getWidth() < VIEWPORT_WIDTH ||
    669 		m_context.getRenderTarget().getHeight() < VIEWPORT_HEIGHT)
    670 	{
    671 		throw tcu::NotSupportedError("Test requires " + de::toString<int>(VIEWPORT_WIDTH) + "x" + de::toString<int>(VIEWPORT_HEIGHT) + " viewport");
    672 	}
    673 
    674 	// resources
    675 
    676 	m_texture = genDummyTexture<glu::Texture2D>(m_context.getRenderContext(), m_context.getContextInfo(), m_texFormat, tcu::IVec2(m_texWidth, m_texHeight));
    677 
    678 	m_testCtx.getLog()	<< tcu::TestLog::Message
    679 						<< "Created texture with format " << glu::getTextureFormatName(m_texFormat)
    680 						<< ", size (" << m_texture->getRefTexture().getWidth() << ", " << m_texture->getRefTexture().getHeight() << ")\n"
    681 						<< "Setting sampling state using " << ((m_stateType == STATE_TEXTURE_PARAM) ? ("texture state") : ("sampler state"))
    682 						<< tcu::TestLog::EndMessage;
    683 
    684 	if (m_samplingFunction == SAMPLE_FILTER)
    685 	{
    686 		const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType());
    687 
    688 		m_renderer = de::MovePtr<gls::TextureTestUtil::TextureRenderer>(new gls::TextureTestUtil::TextureRenderer(m_context.getRenderContext(), m_testCtx.getLog(), glslVersion, glu::PRECISION_HIGHP));
    689 	}
    690 	else
    691 	{
    692 		m_gatherProgram = de::MovePtr<glu::ShaderProgram>(genGatherProgram());
    693 
    694 		m_testCtx.getLog()	<< tcu::TestLog::Message
    695 							<< "Using texture gather to sample texture"
    696 							<< tcu::TestLog::EndMessage
    697 							<< *m_gatherProgram;
    698 
    699 		if (!m_gatherProgram->isOk())
    700 			throw tcu::TestError("failed to build program");
    701 	}
    702 }
    703 
    704 void TextureBorderClampTest::deinit (void)
    705 {
    706 	m_texture.clear();
    707 	m_renderer.clear();
    708 	m_gatherProgram.clear();
    709 }
    710 
    711 TextureBorderClampTest::IterateResult TextureBorderClampTest::iterate (void)
    712 {
    713 	const IterationConfig						iterationConfig		= getIteration(m_iterationNdx);
    714 	const std::string							iterationDesc		= "Iteration " + de::toString(m_iterationNdx+1) + (iterationConfig.description.empty() ? ("") : (" - " + iterationConfig.description));
    715 	const tcu::ScopedLogSection					section				(m_testCtx.getLog(), "Iteration", iterationDesc);
    716 	tcu::Surface								renderedFrame		(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
    717 	const glu::TextureTestUtil::ReferenceParams	samplerParams		= genSamplerParams(iterationConfig);
    718 
    719 	logParams(iterationConfig, samplerParams);
    720 	renderTo(renderedFrame, iterationConfig, samplerParams);
    721 	verifyImage(renderedFrame, iterationConfig, samplerParams);
    722 
    723 	if (++m_iterationNdx == getNumIterations())
    724 	{
    725 		m_result.setTestContextResult(m_testCtx);
    726 		return STOP;
    727 	}
    728 	return CONTINUE;
    729 }
    730 
    731 void TextureBorderClampTest::logParams (const IterationConfig& config, const glu::TextureTestUtil::ReferenceParams& samplerParams)
    732 {
    733 	const std::string				borderColorString	= (m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)   ? (de::toString(config.borderColor.get<deInt32>()))
    734 														: (m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) ? (de::toString(config.borderColor.get<deUint32>()))
    735 														:																  (de::toString(config.borderColor.get<float>()));
    736 
    737 	m_testCtx.getLog()	<< tcu::TestLog::Message
    738 						<< "Rendering full screen quad, tex coords bottom-left: " << config.p0 << ", top-right " << config.p1 << "\n"
    739 						<< "Border color is " << borderColorString << "\n"
    740 						<< "Texture lookup bias: " << samplerParams.colorBias << "\n"
    741 						<< "Texture lookup scale: " << samplerParams.colorScale << "\n"
    742 						<< "Filters: min = " << glu::getTextureFilterName(glu::getGLFilterMode(samplerParams.sampler.minFilter))
    743 							<< ", mag = " << glu::getTextureFilterName(glu::getGLFilterMode(samplerParams.sampler.magFilter)) << "\n"
    744 						<< "Wrap mode: s = " << glu::getRepeatModeStr(config.sWrapMode)
    745 							<< ", t = " << glu::getRepeatModeStr(config.tWrapMode) << "\n"
    746 						<< tcu::TestLog::EndMessage;
    747 
    748 	if (m_sampleMode == tcu::Sampler::MODE_DEPTH)
    749 		m_testCtx.getLog() << tcu::TestLog::Message << "Depth stencil texture mode is DEPTH_COMPONENT" << tcu::TestLog::EndMessage;
    750 	else if (m_sampleMode == tcu::Sampler::MODE_STENCIL)
    751 		m_testCtx.getLog() << tcu::TestLog::Message << "Depth stencil texture mode is STENCIL_INDEX" << tcu::TestLog::EndMessage;
    752 
    753 	if (config.compareMode != GL_NONE)
    754 	{
    755 		m_testCtx.getLog()	<< tcu::TestLog::Message
    756 							<< "Texture mode is COMPARE_REF_TO_TEXTURE, mode = " << glu::getCompareFuncStr(config.compareMode) << "\n"
    757 							<< "Compare reference value = " << config.compareRef << "\n"
    758 							<< tcu::TestLog::EndMessage;
    759 	}
    760 }
    761 
    762 void TextureBorderClampTest::renderTo (tcu::Surface&								surface,
    763 									   const IterationConfig&						config,
    764 									   const glu::TextureTestUtil::ReferenceParams&	samplerParams)
    765 {
    766 	const glw::Functions&						gl			= m_context.getRenderContext().getFunctions();
    767 	const gls::TextureTestUtil::RandomViewport	viewport	(m_context.getRenderTarget(), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, getIterationSeed(config));
    768 	std::vector<float>							texCoord;
    769 	de::MovePtr<glu::Sampler>					sampler;
    770 
    771 	glu::TextureTestUtil::computeQuadTexCoord2D(texCoord, config.p0, config.p1);
    772 
    773 	// Bind to unit 0.
    774 	gl.activeTexture(GL_TEXTURE0);
    775 	gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());
    776 
    777 	if (m_sampleMode == tcu::Sampler::MODE_DEPTH)
    778 		gl.texParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT);
    779 	else if (m_sampleMode == tcu::Sampler::MODE_STENCIL)
    780 		gl.texParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
    781 
    782 	if (config.compareMode == GL_NONE)
    783 	{
    784 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
    785 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_ALWAYS);
    786 	}
    787 	else
    788 	{
    789 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
    790 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, config.compareMode);
    791 	}
    792 
    793 	if (m_stateType == STATE_TEXTURE_PARAM)
    794 	{
    795 		// Setup filtering and wrap modes.
    796 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		glu::getGLWrapMode(samplerParams.sampler.wrapS));
    797 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		glu::getGLWrapMode(samplerParams.sampler.wrapT));
    798 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	glu::getGLFilterMode(samplerParams.sampler.minFilter));
    799 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	glu::getGLFilterMode(samplerParams.sampler.magFilter));
    800 
    801 		switch (m_channelClass)
    802 		{
    803 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
    804 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
    805 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
    806 				gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<float>());
    807 				break;
    808 
    809 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
    810 				gl.texParameterIiv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<deInt32>());
    811 				break;
    812 
    813 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
    814 				gl.texParameterIuiv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<deUint32>());
    815 				break;
    816 
    817 			default:
    818 				DE_ASSERT(false);
    819 		}
    820 	}
    821 	else if (m_stateType == STATE_SAMPLER_PARAM)
    822 	{
    823 		const tcu::Vec4 blue(0.0f, 0.0f, 1.0f, 1.0f);
    824 
    825 		// Setup filtering and wrap modes to bad values
    826 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		GL_REPEAT);
    827 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		GL_REPEAT);
    828 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
    829 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
    830 		gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, blue.getPtr()); // just set some unlikely color
    831 
    832 		// setup sampler to correct values
    833 		sampler = de::MovePtr<glu::Sampler>(new glu::Sampler(m_context.getRenderContext()));
    834 
    835 		gl.samplerParameteri(**sampler, GL_TEXTURE_WRAP_S,		glu::getGLWrapMode(samplerParams.sampler.wrapS));
    836 		gl.samplerParameteri(**sampler, GL_TEXTURE_WRAP_T,		glu::getGLWrapMode(samplerParams.sampler.wrapT));
    837 		gl.samplerParameteri(**sampler, GL_TEXTURE_MIN_FILTER,	glu::getGLFilterMode(samplerParams.sampler.minFilter));
    838 		gl.samplerParameteri(**sampler, GL_TEXTURE_MAG_FILTER,	glu::getGLFilterMode(samplerParams.sampler.magFilter));
    839 
    840 		switch (m_channelClass)
    841 		{
    842 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
    843 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
    844 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
    845 				gl.samplerParameterfv(**sampler, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<float>());
    846 				break;
    847 
    848 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
    849 				gl.samplerParameterIiv(**sampler, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<deInt32>());
    850 				break;
    851 
    852 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
    853 				gl.samplerParameterIuiv(**sampler, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<deUint32>());
    854 				break;
    855 
    856 			default:
    857 				DE_ASSERT(false);
    858 		}
    859 
    860 		gl.bindSampler(0, **sampler);
    861 	}
    862 
    863 	GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
    864 
    865 	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
    866 	renderQuad(&texCoord[0], samplerParams);
    867 	glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, surface.getAccess());
    868 }
    869 
    870 void TextureBorderClampTest::renderQuad (const float* texCoord, const glu::TextureTestUtil::ReferenceParams& samplerParams)
    871 {
    872 	// use TextureRenderer for basic rendering, use custom for gather
    873 	if (m_samplingFunction == SAMPLE_FILTER)
    874 		m_renderer->renderQuad(0, texCoord, samplerParams);
    875 	else
    876 	{
    877 		static const float position[] =
    878 		{
    879 			-1.0f, -1.0f, 0.0f, 1.0f,
    880 			-1.0f, +1.0f, 0.0f, 1.0f,
    881 			+1.0f, -1.0f, 0.0f, 1.0f,
    882 			+1.0f, +1.0f, 0.0f, 1.0f
    883 		};
    884 		static const deUint16 indices[] =
    885 		{
    886 			0, 1, 2, 2, 1, 3
    887 		};
    888 		const glu::VertexArrayBinding vertexArrays[] =
    889 		{
    890 			glu::va::Float("a_position",	4,	4, 0, &position[0]),
    891 			glu::va::Float("a_texcoord",	2,	4, 0, texCoord)
    892 		};
    893 
    894 		const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
    895 		const deUint32			progId	= m_gatherProgram->getProgram();
    896 
    897 		gl.useProgram(progId);
    898 		gl.uniform1i(gl.getUniformLocation(progId, "u_sampler"), 0);
    899 		if (m_useShadowSampler)
    900 			gl.uniform1f(gl.getUniformLocation(progId, "u_ref"), samplerParams.ref);
    901 		gl.uniform4fv(gl.getUniformLocation(progId, "u_colorScale"), 1, samplerParams.colorScale.getPtr());
    902 		gl.uniform4fv(gl.getUniformLocation(progId, "u_colorBias"), 1, samplerParams.colorBias.getPtr());
    903 
    904 		glu::draw(m_context.getRenderContext(), progId, DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0],
    905 					glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
    906 	}
    907 }
    908 
    909 void TextureBorderClampTest::verifyImage (const tcu::Surface&							renderedFrame,
    910 										  const IterationConfig&						config,
    911 										  const glu::TextureTestUtil::ReferenceParams&	samplerParams)
    912 {
    913 	const tcu::PixelFormat	pixelFormat		= m_context.getRenderTarget().getPixelFormat();
    914 
    915 	tcu::LodPrecision		lodPrecision;
    916 	std::vector<float>		texCoord;
    917 	bool					verificationOk;
    918 
    919 	glu::TextureTestUtil::computeQuadTexCoord2D(texCoord, config.p0, config.p1);
    920 
    921 	lodPrecision.derivateBits		= 18;
    922 	lodPrecision.lodBits			= 5;
    923 
    924 	if (samplerParams.sampler.compare == tcu::Sampler::COMPAREMODE_NONE)
    925 	{
    926 		const tcu::TextureFormat		texFormat			= tcu::getEffectiveDepthStencilTextureFormat(m_texture->getRefTexture().getFormat(), m_sampleMode);
    927 		const bool						isNearestMinFilter	= samplerParams.sampler.minFilter == tcu::Sampler::NEAREST || samplerParams.sampler.minFilter == tcu::Sampler::NEAREST_MIPMAP_NEAREST;
    928 		const bool						isNearestMagFilter	= samplerParams.sampler.magFilter == tcu::Sampler::NEAREST;
    929 		const bool						isNearestOnly		= isNearestMinFilter && isNearestMagFilter;
    930 		const bool						isSRGB				= texFormat.order == tcu::TextureFormat::sRGB || texFormat.order == tcu::TextureFormat::sRGBA;
    931 		const int						colorErrorBits		= (isNearestOnly && !isSRGB) ? (1) : (2);
    932 		const tcu::IVec4				colorBits			= tcu::max(glu::TextureTestUtil::getBitsVec(pixelFormat) - tcu::IVec4(colorErrorBits), tcu::IVec4(0));
    933 		tcu::LookupPrecision			lookupPrecision;
    934 
    935 		lookupPrecision.colorThreshold	= tcu::computeFixedPointThreshold(colorBits) / samplerParams.colorScale;
    936 		lookupPrecision.coordBits		= tcu::IVec3(20,20,0);
    937 		lookupPrecision.uvwBits			= tcu::IVec3(5,5,0);
    938 		lookupPrecision.colorMask		= glu::TextureTestUtil::getCompareMask(pixelFormat);
    939 
    940 		if (m_samplingFunction == SAMPLE_FILTER)
    941 		{
    942 			verificationOk = verifyTextureSampleResult(renderedFrame.getAccess(),
    943 													   &texCoord[0],
    944 													   samplerParams,
    945 													   lodPrecision,
    946 													   lookupPrecision);
    947 		}
    948 		else if (m_samplingFunction == SAMPLE_GATHER)
    949 		{
    950 			verificationOk = verifyTextureGatherResult(renderedFrame.getAccess(),
    951 													   &texCoord[0],
    952 													   samplerParams,
    953 													   lookupPrecision);
    954 		}
    955 		else
    956 		{
    957 			DE_ASSERT(false);
    958 			verificationOk = false;
    959 		}
    960 	}
    961 	else
    962 	{
    963 		tcu::TexComparePrecision	texComparePrecision;
    964 		tcu::TexComparePrecision	lowQualityTexComparePrecision;
    965 		tcu::LodPrecision			lowQualityLodPrecision			= lodPrecision;
    966 
    967 		texComparePrecision.coordBits					= tcu::IVec3(20,20,0);
    968 		texComparePrecision.uvwBits						= tcu::IVec3(7,7,0);
    969 		texComparePrecision.pcfBits						= 5;
    970 		texComparePrecision.referenceBits				= 16;
    971 		texComparePrecision.resultBits					= de::max(0, pixelFormat.redBits - 1);
    972 
    973 		lowQualityTexComparePrecision.coordBits			= tcu::IVec3(20,20,0);
    974 		lowQualityTexComparePrecision.uvwBits			= tcu::IVec3(4,4,0);
    975 		lowQualityTexComparePrecision.pcfBits			= 0;
    976 		lowQualityTexComparePrecision.referenceBits		= 16;
    977 		lowQualityTexComparePrecision.resultBits		= de::max(0, pixelFormat.redBits - 1);
    978 
    979 		lowQualityLodPrecision.lodBits					= 4;
    980 
    981 		if (m_samplingFunction == SAMPLE_FILTER)
    982 		{
    983 			verificationOk = verifyTextureCompareResult(renderedFrame.getAccess(),
    984 														&texCoord[0],
    985 														samplerParams,
    986 														texComparePrecision,
    987 														lowQualityTexComparePrecision,
    988 														lodPrecision,
    989 														lowQualityLodPrecision);
    990 		}
    991 		else if (m_samplingFunction == SAMPLE_GATHER)
    992 		{
    993 			verificationOk = verifyTextureGatherCmpResult(renderedFrame.getAccess(),
    994 														  &texCoord[0],
    995 														  samplerParams,
    996 														  texComparePrecision,
    997 														  lowQualityTexComparePrecision);
    998 		}
    999 		else
   1000 		{
   1001 			DE_ASSERT(false);
   1002 			verificationOk = false;
   1003 		}
   1004 	}
   1005 
   1006 	if (!verificationOk)
   1007 		m_result.fail("Image verification failed");
   1008 }
   1009 
   1010 bool TextureBorderClampTest::verifyTextureSampleResult (const tcu::ConstPixelBufferAccess&				renderedFrame,
   1011 														const float*									texCoord,
   1012 														const glu::TextureTestUtil::ReferenceParams&	samplerParams,
   1013 														const tcu::LodPrecision&						lodPrecision,
   1014 													    const tcu::LookupPrecision&						lookupPrecision)
   1015 {
   1016 	const tcu::PixelFormat			pixelFormat			= m_context.getRenderTarget().getPixelFormat();
   1017 	tcu::Surface					reference			(renderedFrame.getWidth(), renderedFrame.getHeight());
   1018 	tcu::Surface					errorMask			(renderedFrame.getWidth(), renderedFrame.getHeight());
   1019 	int								numFailedPixels;
   1020 
   1021 	glu::TextureTestUtil::sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), m_texture->getRefTexture(), texCoord, samplerParams);
   1022 
   1023 	numFailedPixels = glu::TextureTestUtil::computeTextureLookupDiff(renderedFrame, reference.getAccess(), errorMask.getAccess(), m_texture->getRefTexture(),
   1024 																	 texCoord, samplerParams, lookupPrecision, lodPrecision, m_testCtx.getWatchDog());
   1025 
   1026 	if (numFailedPixels > 0)
   1027 		m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
   1028 	m_testCtx.getLog()	<< tcu::TestLog::ImageSet("VerifyResult", "Verification result")
   1029 						<< tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame);
   1030 	if (numFailedPixels > 0)
   1031 	{
   1032 		m_testCtx.getLog()	<< tcu::TestLog::Image("Reference", "Ideal reference image", reference)
   1033 							<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
   1034 	}
   1035 	m_testCtx.getLog() << tcu::TestLog::EndImageSet;
   1036 
   1037 	return (numFailedPixels == 0);
   1038 }
   1039 
   1040 bool TextureBorderClampTest::verifyTextureCompareResult (const tcu::ConstPixelBufferAccess&				renderedFrame,
   1041 														 const float*									texCoord,
   1042 														 const glu::TextureTestUtil::ReferenceParams&	samplerParams,
   1043 													     const tcu::TexComparePrecision&				texComparePrecision,
   1044 													     const tcu::TexComparePrecision&				lowQualityTexComparePrecision,
   1045 														 const tcu::LodPrecision&						lodPrecision,
   1046 														 const tcu::LodPrecision&						lowQualityLodPrecision)
   1047 {
   1048 	const tcu::PixelFormat						pixelFormat				= m_context.getRenderTarget().getPixelFormat();
   1049 	const int									colorErrorBits			= 1;
   1050 	const tcu::IVec4							nonShadowBits			= tcu::max(glu::TextureTestUtil::getBitsVec(pixelFormat) - tcu::IVec4(colorErrorBits), tcu::IVec4(0));
   1051 	const tcu::Vec3								nonShadowThreshold		= tcu::computeFixedPointThreshold(nonShadowBits).swizzle(1,2,3);
   1052 	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
   1053 	const tcu::Texture2DView					effectiveView			= tcu::getEffectiveTextureView(m_texture->getRefTexture(), srcLevelStorage, samplerParams.sampler);
   1054 	tcu::Surface								reference				(renderedFrame.getWidth(), renderedFrame.getHeight());
   1055 	tcu::Surface								errorMask				(renderedFrame.getWidth(), renderedFrame.getHeight());
   1056 	int											numFailedPixels;
   1057 
   1058 	glu::TextureTestUtil::sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), effectiveView, texCoord, samplerParams);
   1059 
   1060 	numFailedPixels = glu::TextureTestUtil::computeTextureCompareDiff(renderedFrame, reference.getAccess(), errorMask.getAccess(), effectiveView,
   1061 																	  texCoord, samplerParams, texComparePrecision, lodPrecision, nonShadowThreshold);
   1062 
   1063 	if (numFailedPixels > 0)
   1064 	{
   1065 		m_testCtx.getLog()	<< tcu::TestLog::Message
   1066 							<< "Warning: Verification assuming high-quality PCF filtering failed."
   1067 							<< tcu::TestLog::EndMessage;
   1068 
   1069 		numFailedPixels = glu::TextureTestUtil::computeTextureCompareDiff(renderedFrame, reference.getAccess(), errorMask.getAccess(), effectiveView,
   1070 																		  texCoord, samplerParams, lowQualityTexComparePrecision, lowQualityLodPrecision, nonShadowThreshold);
   1071 
   1072 		if (numFailedPixels > 0)
   1073 			m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << tcu::TestLog::EndMessage;
   1074 		else if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
   1075 			m_result.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality result");
   1076 	}
   1077 
   1078 	if (numFailedPixels > 0)
   1079 		m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
   1080 	m_testCtx.getLog()	<< tcu::TestLog::ImageSet("VerifyResult", "Verification result")
   1081 						<< tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame);
   1082 	if (numFailedPixels > 0)
   1083 	{
   1084 		m_testCtx.getLog()	<< tcu::TestLog::Image("Reference", "Ideal reference image", reference)
   1085 							<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
   1086 	}
   1087 	m_testCtx.getLog() << tcu::TestLog::EndImageSet;
   1088 
   1089 	return (numFailedPixels == 0);
   1090 }
   1091 
   1092 template <typename T>
   1093 static inline T triQuadInterpolate (const T (&values)[4], float xFactor, float yFactor)
   1094 {
   1095 	if (xFactor + yFactor < 1.0f)
   1096 		return values[0] + (values[2]-values[0])*xFactor		+ (values[1]-values[0])*yFactor;
   1097 	else
   1098 		return values[3] + (values[1]-values[3])*(1.0f-xFactor)	+ (values[2]-values[3])*(1.0f-yFactor);
   1099 }
   1100 
   1101 bool TextureBorderClampTest::verifyTextureGatherResult (const tcu::ConstPixelBufferAccess&				renderedFrame,
   1102 														const float*									texCoordArray,
   1103 														const glu::TextureTestUtil::ReferenceParams&	samplerParams,
   1104 														const tcu::LookupPrecision&						lookupPrecision)
   1105 {
   1106 	const tcu::Vec2 texCoords[4] =
   1107 	{
   1108 		tcu::Vec2(texCoordArray[0], texCoordArray[1]),
   1109 		tcu::Vec2(texCoordArray[2], texCoordArray[3]),
   1110 		tcu::Vec2(texCoordArray[4], texCoordArray[5]),
   1111 		tcu::Vec2(texCoordArray[6], texCoordArray[7]),
   1112 	};
   1113 
   1114 	const tcu::PixelFormat						pixelFormat			= m_context.getRenderTarget().getPixelFormat();
   1115 	const deUint8								fbColormask			= tcu::getColorMask(pixelFormat);
   1116 
   1117 	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
   1118 	const tcu::Texture2DView					effectiveView		= tcu::getEffectiveTextureView(m_texture->getRefTexture(), srcLevelStorage, samplerParams.sampler);
   1119 
   1120 	tcu::Surface								reference			(renderedFrame.getWidth(), renderedFrame.getHeight());
   1121 	tcu::Surface								errorMask			(renderedFrame.getWidth(), renderedFrame.getHeight());
   1122 	int											numFailedPixels		= 0;
   1123 
   1124 	tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec());
   1125 
   1126 	for (int py = 0; py < reference.getHeight(); ++py)
   1127 	for (int px = 0; px < reference.getWidth(); ++px)
   1128 	{
   1129 		const tcu::Vec2			viewportCoord	= (tcu::Vec2((float)px, (float)py) + tcu::Vec2(0.5f)) / tcu::Vec2((float)reference.getWidth(), (float)reference.getHeight());
   1130 		const tcu::Vec2			texCoord		= triQuadInterpolate(texCoords, viewportCoord.x(), viewportCoord.y());
   1131 		const tcu::Vec4			referenceValue	= effectiveView.gatherOffsets(samplerParams.sampler, texCoord.x(), texCoord.y(), 0, glu::getDefaultGatherOffsets());
   1132 		const tcu::Vec4			referencePixel	= referenceValue * samplerParams.colorScale + samplerParams.colorBias;
   1133 		const tcu::Vec4			resultPixel		= renderedFrame.getPixel(px, py);
   1134 		const tcu::Vec4			resultValue		= (resultPixel - samplerParams.colorBias) / samplerParams.colorScale;
   1135 
   1136 		reference.setPixel(px, py, tcu::toRGBAMasked(referenceValue, fbColormask));
   1137 
   1138 		if (tcu::boolAny(tcu::logicalAnd(lookupPrecision.colorMask,
   1139 										 tcu::greaterThan(tcu::absDiff(resultPixel, referencePixel),
   1140 														  lookupPrecision.colorThreshold))))
   1141 		{
   1142 			if (!tcu::isGatherOffsetsResultValid(effectiveView, samplerParams.sampler, lookupPrecision, texCoord, 0, glu::getDefaultGatherOffsets(), resultValue))
   1143 			{
   1144 				errorMask.setPixel(px, py, tcu::RGBA::red());
   1145 				++numFailedPixels;
   1146 			}
   1147 		}
   1148 	}
   1149 
   1150 	if (numFailedPixels > 0)
   1151 		m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
   1152 	m_testCtx.getLog()	<< tcu::TestLog::ImageSet("VerifyResult", "Verification result")
   1153 						<< tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame);
   1154 	if (numFailedPixels > 0)
   1155 	{
   1156 		m_testCtx.getLog()	<< tcu::TestLog::Image("Reference", "Ideal reference image", reference)
   1157 							<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
   1158 	}
   1159 	m_testCtx.getLog() << tcu::TestLog::EndImageSet;
   1160 
   1161 	return (numFailedPixels == 0);
   1162 }
   1163 
   1164 bool TextureBorderClampTest::verifyTextureGatherCmpResult (const tcu::ConstPixelBufferAccess&			renderedFrame,
   1165 														   const float*									texCoordArray,
   1166 														   const glu::TextureTestUtil::ReferenceParams&	samplerParams,
   1167 														   const tcu::TexComparePrecision&				texComparePrecision,
   1168 														   const tcu::TexComparePrecision&				lowQualityTexComparePrecision)
   1169 {
   1170 	const tcu::Vec2 texCoords[4] =
   1171 	{
   1172 		tcu::Vec2(texCoordArray[0], texCoordArray[1]),
   1173 		tcu::Vec2(texCoordArray[2], texCoordArray[3]),
   1174 		tcu::Vec2(texCoordArray[4], texCoordArray[5]),
   1175 		tcu::Vec2(texCoordArray[6], texCoordArray[7]),
   1176 	};
   1177 
   1178 	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
   1179 	const tcu::Texture2DView					effectiveView		= tcu::getEffectiveTextureView(m_texture->getRefTexture(), srcLevelStorage, samplerParams.sampler);
   1180 
   1181 	const tcu::PixelFormat						pixelFormat			= m_context.getRenderTarget().getPixelFormat();
   1182 	const tcu::BVec4							colorMask			= glu::TextureTestUtil::getCompareMask(pixelFormat);
   1183 	const deUint8								fbColormask			= tcu::getColorMask(pixelFormat);
   1184 	tcu::Surface								reference			(renderedFrame.getWidth(), renderedFrame.getHeight());
   1185 	tcu::Surface								errorMask			(renderedFrame.getWidth(), renderedFrame.getHeight());
   1186 	int											numFailedPixels		= 0;
   1187 	bool										lowQuality			= false;
   1188 
   1189 	tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec());
   1190 
   1191 	for (int py = 0; py < reference.getHeight(); ++py)
   1192 	for (int px = 0; px < reference.getWidth(); ++px)
   1193 	{
   1194 		const tcu::Vec2			viewportCoord	= (tcu::Vec2((float)px, (float)py) + tcu::Vec2(0.5f)) / tcu::Vec2((float)reference.getWidth(), (float)reference.getHeight());
   1195 		const tcu::Vec2			texCoord		= triQuadInterpolate(texCoords, viewportCoord.x(), viewportCoord.y());
   1196 		const float				refZ			= samplerParams.ref;
   1197 		const tcu::Vec4			referenceValue	= effectiveView.gatherOffsetsCompare(samplerParams.sampler, refZ, texCoord.x(), texCoord.y(), glu::getDefaultGatherOffsets());
   1198 		const tcu::Vec4			resultValue		= renderedFrame.getPixel(px, py);
   1199 
   1200 		reference.setPixel(px, py, tcu::toRGBAMasked(referenceValue, fbColormask));
   1201 
   1202 		if (tcu::boolAny(tcu::logicalAnd(colorMask, tcu::notEqual(referenceValue, resultValue))))
   1203 		{
   1204 			if (!tcu::isGatherOffsetsCompareResultValid(effectiveView, samplerParams.sampler, texComparePrecision, texCoord, glu::getDefaultGatherOffsets(), refZ, resultValue))
   1205 			{
   1206 				lowQuality = true;
   1207 
   1208 				// fall back to low quality verification
   1209 				if (!tcu::isGatherOffsetsCompareResultValid(effectiveView, samplerParams.sampler, lowQualityTexComparePrecision, texCoord, glu::getDefaultGatherOffsets(), refZ, resultValue))
   1210 				{
   1211 					errorMask.setPixel(px, py, tcu::RGBA::red());
   1212 					++numFailedPixels;
   1213 				}
   1214 			}
   1215 		}
   1216 	}
   1217 
   1218 	if (numFailedPixels > 0)
   1219 		m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
   1220 	else if (lowQuality)
   1221 	{
   1222 		m_testCtx.getLog() << tcu::TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << tcu::TestLog::EndMessage;
   1223 		m_result.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality result");
   1224 	}
   1225 
   1226 	m_testCtx.getLog()	<< tcu::TestLog::ImageSet("VerifyResult", "Verification result")
   1227 						<< tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame);
   1228 	if (numFailedPixels > 0)
   1229 	{
   1230 		m_testCtx.getLog()	<< tcu::TestLog::Image("Reference", "Ideal reference image", reference)
   1231 							<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
   1232 	}
   1233 	m_testCtx.getLog() << tcu::TestLog::EndImageSet;
   1234 
   1235 	return (numFailedPixels == 0);
   1236 }
   1237 
   1238 const glu::Texture2D* TextureBorderClampTest::getTexture (void) const
   1239 {
   1240 	return m_texture.get();
   1241 }
   1242 
   1243 deUint32 TextureBorderClampTest::getIterationSeed (const IterationConfig& config) const
   1244 {
   1245 	tcu::SeedBuilder builder;
   1246 	builder	<< std::string(getName())
   1247 			<< m_iterationNdx
   1248 			<< m_texFormat
   1249 			<< config.minFilter << config.magFilter
   1250 			<< m_texture->getRefTexture().getWidth() << m_texture->getRefTexture().getHeight();
   1251 	return builder.get();
   1252 }
   1253 
   1254 glu::TextureTestUtil::ReferenceParams TextureBorderClampTest::genSamplerParams (const IterationConfig& config) const
   1255 {
   1256 	const tcu::TextureFormat				texFormat		= tcu::getEffectiveDepthStencilTextureFormat(m_texture->getRefTexture().getFormat(), m_sampleMode);
   1257 	glu::TextureTestUtil::ReferenceParams	refParams		(glu::TextureTestUtil::TEXTURETYPE_2D);
   1258 
   1259 	refParams.sampler					= glu::mapGLSampler(config.sWrapMode, config.tWrapMode, config.minFilter, config.magFilter);
   1260 	refParams.sampler.borderColor		= config.borderColor;
   1261 	refParams.sampler.compare			= (!m_useShadowSampler) ? (tcu::Sampler::COMPAREMODE_NONE) : (glu::mapGLCompareFunc(config.compareMode));
   1262 	refParams.sampler.depthStencilMode	= m_sampleMode;
   1263 	refParams.lodMode					= glu::TextureTestUtil::LODMODE_EXACT;
   1264 	refParams.samplerType				= (!m_useShadowSampler) ? (glu::TextureTestUtil::getSamplerType(texFormat)) : (glu::TextureTestUtil::SAMPLERTYPE_SHADOW);
   1265 	refParams.colorScale				= config.lookupScale;
   1266 	refParams.colorBias					= config.lookupBias;
   1267 	refParams.ref						= config.compareRef;
   1268 
   1269 	// compare can only be used with depth textures
   1270 	if (!isDepthFormat(m_texFormat, m_sampleMode))
   1271 		DE_ASSERT(refParams.sampler.compare == tcu::Sampler::COMPAREMODE_NONE);
   1272 
   1273 	// sampler type must match compare mode
   1274 	DE_ASSERT(m_useShadowSampler == (config.compareMode != GL_NONE));
   1275 
   1276 	// in gather, weird mapping is most likely an error
   1277 	if (m_samplingFunction == SAMPLE_GATHER)
   1278 	{
   1279 		DE_ASSERT(refParams.colorScale == tcu::Vec4(refParams.colorScale.x()));
   1280 		DE_ASSERT(refParams.colorBias == tcu::Vec4(refParams.colorBias.x()));
   1281 	}
   1282 
   1283 	return refParams;
   1284 }
   1285 
   1286 glu::ShaderProgram* TextureBorderClampTest::genGatherProgram (void) const
   1287 {
   1288 	const std::string	glslVersionDecl	= glu::getGLSLVersionDeclaration(glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType()));
   1289 	const std::string	vtxSource		= glslVersionDecl + "\n"
   1290 										"in highp vec4 a_position;\n"
   1291 										"in highp vec2 a_texcoord;\n"
   1292 										"out highp vec2 v_texcoord;\n"
   1293 										"void main()\n"
   1294 										"{\n"
   1295 										"	gl_Position = a_position;\n"
   1296 										"	v_texcoord = a_texcoord;\n"
   1297 										"}\n";
   1298 	const char*			samplerType;
   1299 	const char*			lookup;
   1300 	std::ostringstream	fragSource;
   1301 
   1302 	if (m_useShadowSampler)
   1303 	{
   1304 		samplerType	= "sampler2DShadow";
   1305 		lookup		= "textureGather(u_sampler, v_texcoord, u_ref)";
   1306 	}
   1307 	else
   1308 	{
   1309 		switch (m_channelClass)
   1310 		{
   1311 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
   1312 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
   1313 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
   1314 				samplerType	= "sampler2D";
   1315 				lookup		= "textureGather(u_sampler, v_texcoord)";
   1316 				break;
   1317 
   1318 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
   1319 				samplerType	= "isampler2D";
   1320 				lookup		= "vec4(textureGather(u_sampler, v_texcoord))";
   1321 				break;
   1322 
   1323 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
   1324 				samplerType	= "usampler2D";
   1325 				lookup		= "vec4(textureGather(u_sampler, v_texcoord))";
   1326 				break;
   1327 
   1328 			default:
   1329 				samplerType	= "";
   1330 				lookup		= "";
   1331 				DE_ASSERT(false);
   1332 		}
   1333 	}
   1334 
   1335 	fragSource	<<	glslVersionDecl + "\n"
   1336 					"uniform highp " << samplerType << " u_sampler;\n"
   1337 					"uniform highp vec4 u_colorScale;\n"
   1338 					"uniform highp vec4 u_colorBias;\n"
   1339 				<<	((m_useShadowSampler) ? ("uniform highp float u_ref;\n") : (""))
   1340 				<<	"in highp vec2 v_texcoord;\n"
   1341 					"layout(location=0) out highp vec4 o_color;\n"
   1342 					"void main()\n"
   1343 					"{\n"
   1344 					"	o_color = " << lookup << " * u_colorScale + u_colorBias;\n"
   1345 					"}\n";
   1346 
   1347 	return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(vtxSource) << glu::FragmentSource(fragSource.str()));
   1348 }
   1349 
   1350 class TextureBorderClampFormatCase : public TextureBorderClampTest
   1351 {
   1352 public:
   1353 									TextureBorderClampFormatCase	(Context&						context,
   1354 																	 const char*					name,
   1355 																	 const char*					description,
   1356 																	 deUint32						texFormat,
   1357 																	 tcu::Sampler::DepthStencilMode	mode,
   1358 																	 StateType						stateType,
   1359 																	 SizeType						sizeType,
   1360 																	 deUint32						filter,
   1361 																	 SamplingFunction				samplingFunction);
   1362 
   1363 private:
   1364 	void							init							(void);
   1365 
   1366 	int								getNumIterations				(void) const;
   1367 	IterationConfig					getIteration					(int ndx) const;
   1368 
   1369 	const SizeType					m_sizeType;
   1370 	const deUint32					m_filter;
   1371 
   1372 	std::vector<IterationConfig>	m_iterations;
   1373 };
   1374 
   1375 
   1376 TextureBorderClampFormatCase::TextureBorderClampFormatCase	(Context&						context,
   1377 															 const char*					name,
   1378 															 const char*					description,
   1379 															 deUint32						texFormat,
   1380 															 tcu::Sampler::DepthStencilMode	mode,
   1381 															 StateType						stateType,
   1382 															 SizeType						sizeType,
   1383 															 deUint32						filter,
   1384 															 SamplingFunction				samplingFunction)
   1385 	: TextureBorderClampTest(context,
   1386 							 name,
   1387 							 description,
   1388 							 texFormat,
   1389 							 mode,
   1390 							 stateType,
   1391 							 (sizeType == SIZE_POT) ? (32) : (17),
   1392 							 (sizeType == SIZE_POT) ? (16) : (31),
   1393 							 samplingFunction)
   1394 	, m_sizeType			(sizeType)
   1395 	, m_filter				(filter)
   1396 {
   1397 	if (m_sizeType == SIZE_POT)
   1398 		DE_ASSERT(deIsPowerOfTwo32(m_texWidth) && deIsPowerOfTwo32(m_texHeight));
   1399 	else
   1400 		DE_ASSERT(!deIsPowerOfTwo32(m_texWidth) && !deIsPowerOfTwo32(m_texHeight));
   1401 
   1402 	if (glu::isCompressedFormat(texFormat))
   1403 	{
   1404 		const tcu::CompressedTexFormat	compressedFormat	= glu::mapGLCompressedTexFormat(texFormat);
   1405 		const tcu::IVec3				blockPixelSize		= tcu::getBlockPixelSize(compressedFormat);
   1406 
   1407 		// is (not) multiple of a block size
   1408 		if (m_sizeType == SIZE_POT)
   1409 			DE_ASSERT((m_texWidth % blockPixelSize.x()) == 0 && (m_texHeight % blockPixelSize.y()) == 0);
   1410 		else
   1411 			DE_ASSERT((m_texWidth % blockPixelSize.x()) != 0 && (m_texHeight % blockPixelSize.y()) != 0);
   1412 
   1413 		DE_UNREF(blockPixelSize);
   1414 	}
   1415 }
   1416 
   1417 void TextureBorderClampFormatCase::init (void)
   1418 {
   1419 	TextureBorderClampTest::init();
   1420 
   1421 	// \note TextureBorderClampTest::init() creates texture
   1422 	const tcu::TextureFormat		texFormat		= tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode);
   1423 	const tcu::TextureFormatInfo	texFormatInfo	= tcu::getTextureFormatInfo(texFormat);
   1424 
   1425 	// iterations
   1426 
   1427 	{
   1428 		IterationConfig iteration;
   1429 		iteration.p0			= tcu::Vec2(-1.5f, -3.0f);
   1430 		iteration.p1			= tcu::Vec2( 1.5f,  2.5f);
   1431 		iteration.borderColor	= mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.3f, 0.7f, 0.2f, 0.5f));
   1432 		m_iterations.push_back(iteration);
   1433 	}
   1434 	{
   1435 		IterationConfig iteration;
   1436 		iteration.p0			= tcu::Vec2(-0.5f, 0.75f);
   1437 		iteration.p1			= tcu::Vec2(0.25f, 1.25f);
   1438 		iteration.borderColor	= mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.9f, 0.2f, 0.4f, 0.6f));
   1439 		m_iterations.push_back(iteration);
   1440 	}
   1441 
   1442 	// common parameters
   1443 	for (int ndx = 0; ndx < (int)m_iterations.size(); ++ndx)
   1444 	{
   1445 		IterationConfig& iteration = m_iterations[ndx];
   1446 
   1447 		if (m_samplingFunction == SAMPLE_GATHER)
   1448 		{
   1449 			iteration.lookupScale	= tcu::Vec4(texFormatInfo.lookupScale.x());
   1450 			iteration.lookupBias	= tcu::Vec4(texFormatInfo.lookupBias.x());
   1451 		}
   1452 		else
   1453 		{
   1454 			iteration.lookupScale	= texFormatInfo.lookupScale;
   1455 			iteration.lookupBias	= texFormatInfo.lookupBias;
   1456 		}
   1457 
   1458 		iteration.minFilter		= m_filter;
   1459 		iteration.magFilter		= m_filter;
   1460 		iteration.sWrapMode		= GL_CLAMP_TO_BORDER;
   1461 		iteration.tWrapMode		= GL_CLAMP_TO_BORDER;
   1462 		iteration.compareMode	= GL_NONE;
   1463 		iteration.compareRef	= 0.0f;
   1464 	}
   1465 }
   1466 
   1467 int TextureBorderClampFormatCase::getNumIterations	(void) const
   1468 {
   1469 	return (int)m_iterations.size();
   1470 }
   1471 
   1472 TextureBorderClampTest::IterationConfig TextureBorderClampFormatCase::getIteration (int ndx) const
   1473 {
   1474 	return m_iterations[ndx];
   1475 }
   1476 
   1477 class TextureBorderClampRangeClampCase : public TextureBorderClampTest
   1478 {
   1479 public:
   1480 									TextureBorderClampRangeClampCase	(Context&						context,
   1481 																		 const char*					name,
   1482 																		 const char*					description,
   1483 																		 deUint32						texFormat,
   1484 																		 tcu::Sampler::DepthStencilMode	mode,
   1485 																		 deUint32						filter);
   1486 
   1487 private:
   1488 	void							init								(void);
   1489 
   1490 	int								getNumIterations					(void) const;
   1491 	IterationConfig					getIteration						(int ndx) const;
   1492 
   1493 	const deUint32					m_filter;
   1494 	std::vector<IterationConfig>	m_iterations;
   1495 };
   1496 
   1497 TextureBorderClampRangeClampCase::TextureBorderClampRangeClampCase	(Context&						context,
   1498 																	 const char*					name,
   1499 																	 const char*					description,
   1500 																	 deUint32						texFormat,
   1501 																	 tcu::Sampler::DepthStencilMode	mode,
   1502 																	 deUint32						filter)
   1503 	: TextureBorderClampTest(context, name, description, texFormat, mode, TextureBorderClampTest::STATE_TEXTURE_PARAM, 8, 32, SAMPLE_FILTER)
   1504 	, m_filter				(filter)
   1505 {
   1506 }
   1507 
   1508 void TextureBorderClampRangeClampCase::init (void)
   1509 {
   1510 	TextureBorderClampTest::init();
   1511 
   1512 	const tcu::TextureFormat	texFormat		= tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode);
   1513 	const bool					isDepth			= isDepthFormat(m_texFormat, m_sampleMode);
   1514 	const bool					isFloat			= m_channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT;
   1515 	const bool					isFixed			= m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
   1516 	const bool					isPureInteger	= m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
   1517 
   1518 	if (isDepth || isFloat)
   1519 	{
   1520 		// infinities are commonly used values on depth/float borders
   1521 		{
   1522 			IterationConfig iteration;
   1523 			iteration.p0			= tcu::Vec2(-1.2f, -3.0f);
   1524 			iteration.p1			= tcu::Vec2( 1.2f,  2.5f);
   1525 			iteration.borderColor	= rr::GenericVec4(tcu::Vec4(std::numeric_limits<float>::infinity()));
   1526 			iteration.lookupScale	= tcu::Vec4(0.5f); // scale & bias to [0.25, 0.5] range to make out-of-range values visible
   1527 			iteration.lookupBias	= tcu::Vec4(0.25f);
   1528 			iteration.description	= "border value infinity";
   1529 			m_iterations.push_back(iteration);
   1530 		}
   1531 		{
   1532 			IterationConfig iteration;
   1533 			iteration.p0			= tcu::Vec2(-0.25f, -0.75f);
   1534 			iteration.p1			= tcu::Vec2( 2.25f,  1.25f);
   1535 			iteration.borderColor	= rr::GenericVec4(tcu::Vec4(-std::numeric_limits<float>::infinity()));
   1536 			iteration.lookupScale	= tcu::Vec4(0.5f);
   1537 			iteration.lookupBias	= tcu::Vec4(0.25f);
   1538 			iteration.description	= "border value negative infinity";
   1539 			m_iterations.push_back(iteration);
   1540 		}
   1541 	}
   1542 	else if (isPureInteger)
   1543 	{
   1544 		const tcu::IVec4			numBits		= tcu::getTextureFormatBitDepth(texFormat);
   1545 		const bool					isSigned	= m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER;
   1546 
   1547 		// can't overflow 32bit integers with 32bit integers
   1548 		for (int ndx = 0; ndx < 4; ++ndx)
   1549 			DE_ASSERT(numBits[ndx] == 0 || numBits[ndx] == 8 || numBits[ndx] == 16);
   1550 
   1551 		const tcu::IVec4	minValue		= getNBitIntegerVec4MinValue(isSigned, numBits);
   1552 		const tcu::IVec4	maxValue		= getNBitIntegerVec4MaxValue(isSigned, numBits);
   1553 		const tcu::IVec4	valueRange		= maxValue - minValue;
   1554 		const tcu::IVec4	divSafeRange	((valueRange[0]==0) ? (1) : (valueRange[0]),
   1555 											 (valueRange[1]==0) ? (1) : (valueRange[1]),
   1556 											 (valueRange[2]==0) ? (1) : (valueRange[2]),
   1557 											 (valueRange[3]==0) ? (1) : (valueRange[3]));
   1558 
   1559 		// format max
   1560 		{
   1561 			const tcu::IVec4 value = maxValue + tcu::IVec4(1);
   1562 
   1563 			IterationConfig iteration;
   1564 			iteration.p0			= tcu::Vec2(-1.2f, -3.0f);
   1565 			iteration.p1			= tcu::Vec2( 1.2f,  2.5f);
   1566 			iteration.borderColor	= (isSigned) ? (rr::GenericVec4(value)) : (rr::GenericVec4(value.cast<deUint32>()));
   1567 			iteration.lookupScale	= tcu::Vec4(0.5f) / divSafeRange.cast<float>();
   1568 			iteration.lookupBias	= (isSigned) ? (tcu::Vec4(0.5f)) : (tcu::Vec4(0.25f));
   1569 			iteration.description	= "border values one larger than maximum";
   1570 			m_iterations.push_back(iteration);
   1571 		}
   1572 		// format min
   1573 		if (isSigned)
   1574 		{
   1575 			const tcu::IVec4 value = minValue - tcu::IVec4(1);
   1576 
   1577 			IterationConfig iteration;
   1578 			iteration.p0			= tcu::Vec2(-0.25f, -0.75f);
   1579 			iteration.p1			= tcu::Vec2( 2.25f,  1.25f);
   1580 			iteration.borderColor	= rr::GenericVec4(value);
   1581 			iteration.lookupScale	= tcu::Vec4(0.5f) / divSafeRange.cast<float>();
   1582 			iteration.lookupBias	= tcu::Vec4(0.5f);
   1583 			iteration.description	= "border values one less than minimum";
   1584 			m_iterations.push_back(iteration);
   1585 		}
   1586 		// (u)int32 max
   1587 		{
   1588 			const tcu::IVec4 value = (isSigned) ? (tcu::IVec4(std::numeric_limits<deInt32>::max())) : (tcu::IVec4(std::numeric_limits<deUint32>::max()));
   1589 
   1590 			IterationConfig iteration;
   1591 			iteration.p0			= tcu::Vec2(-1.6f, -2.1f);
   1592 			iteration.p1			= tcu::Vec2( 1.2f,  3.5f);
   1593 			iteration.borderColor	= (isSigned) ? (rr::GenericVec4(value)) : (rr::GenericVec4(value.cast<deUint32>()));
   1594 			iteration.lookupScale	= tcu::Vec4(0.5f) / divSafeRange.cast<float>();
   1595 			iteration.lookupBias	= tcu::Vec4(0.25f);
   1596 			iteration.description	= "border values 32-bit maximum";
   1597 			m_iterations.push_back(iteration);
   1598 		}
   1599 		// int32 min
   1600 		if (isSigned)
   1601 		{
   1602 			const tcu::IVec4 value = tcu::IVec4(std::numeric_limits<deInt32>::min());
   1603 
   1604 			IterationConfig iteration;
   1605 			iteration.p0			= tcu::Vec2(-2.6f, -4.0f);
   1606 			iteration.p1			= tcu::Vec2( 1.1f,  1.5f);
   1607 			iteration.borderColor	= rr::GenericVec4(value);
   1608 			iteration.lookupScale	= tcu::Vec4(0.5f) / divSafeRange.cast<float>();
   1609 			iteration.lookupBias	= tcu::Vec4(0.25f);
   1610 			iteration.description	= "border values 0";
   1611 			m_iterations.push_back(iteration);
   1612 		}
   1613 	}
   1614 	else if (isFixed)
   1615 	{
   1616 		const bool		isSigned	= m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;;
   1617 		const tcu::Vec4	lookupBias	= (isSigned) ? (tcu::Vec4(0.5f))    : (tcu::Vec4(0.25f)); // scale & bias to [0.25, 0.5] range to make out-of-range values visible
   1618 		const tcu::Vec4	lookupScale	= (isSigned) ? (tcu::Vec4(0.25f))   : (tcu::Vec4(0.5f));
   1619 
   1620 		{
   1621 			IterationConfig iteration;
   1622 			iteration.p0			= tcu::Vec2(-1.2f, -3.0f);
   1623 			iteration.p1			= tcu::Vec2( 1.2f,  2.5f);
   1624 			iteration.borderColor	= mapToFormatColorUnits(texFormat, tcu::Vec4(1.1f, 1.3f, 2.2f, 1.3f));
   1625 			iteration.lookupScale	= lookupScale;
   1626 			iteration.lookupBias	= lookupBias;
   1627 			iteration.description	= "border values larger than maximum";
   1628 			m_iterations.push_back(iteration);
   1629 		}
   1630 		{
   1631 			IterationConfig iteration;
   1632 			iteration.p0			= tcu::Vec2(-0.25f, -0.75f);
   1633 			iteration.p1			= tcu::Vec2( 2.25f,  1.25f);
   1634 			iteration.borderColor	= mapToFormatColorUnits(texFormat, tcu::Vec4(-0.2f, -0.9f, -2.4f, -0.6f));
   1635 			iteration.lookupScale	= lookupScale;
   1636 			iteration.lookupBias	= lookupBias;
   1637 			iteration.description	= "border values less than minimum";
   1638 			m_iterations.push_back(iteration);
   1639 		}
   1640 	}
   1641 	else
   1642 		DE_ASSERT(false);
   1643 
   1644 	// common parameters
   1645 	for (int ndx = 0; ndx < (int)m_iterations.size(); ++ndx)
   1646 	{
   1647 		IterationConfig& iteration = m_iterations[ndx];
   1648 
   1649 		iteration.minFilter		= m_filter;
   1650 		iteration.magFilter		= m_filter;
   1651 		iteration.sWrapMode		= GL_CLAMP_TO_BORDER;
   1652 		iteration.tWrapMode		= GL_CLAMP_TO_BORDER;
   1653 		iteration.compareMode	= GL_NONE;
   1654 		iteration.compareRef	= 0.0f;
   1655 	}
   1656 }
   1657 
   1658 int TextureBorderClampRangeClampCase::getNumIterations	(void) const
   1659 {
   1660 	return (int)m_iterations.size();
   1661 }
   1662 
   1663 TextureBorderClampTest::IterationConfig TextureBorderClampRangeClampCase::getIteration (int ndx) const
   1664 {
   1665 	return m_iterations[ndx];
   1666 }
   1667 
   1668 class TextureBorderClampPerAxisCase2D : public TextureBorderClampTest
   1669 {
   1670 public:
   1671 									TextureBorderClampPerAxisCase2D	(Context&						context,
   1672 																	 const char*					name,
   1673 																	 const char*					description,
   1674 																	 deUint32						texFormat,
   1675 																	 tcu::Sampler::DepthStencilMode	mode,
   1676 																	 SizeType						sizeType,
   1677 																	 deUint32						filter,
   1678 																	 deUint32						texSWrap,
   1679 																	 deUint32						texTWrap,
   1680 																	 SamplingFunction				samplingFunction);
   1681 
   1682 private:
   1683 	void							init							(void);
   1684 
   1685 	int								getNumIterations				(void) const;
   1686 	IterationConfig					getIteration					(int ndx) const;
   1687 
   1688 	const deUint32					m_texSWrap;
   1689 	const deUint32					m_texTWrap;
   1690 	const deUint32					m_filter;
   1691 
   1692 	std::vector<IterationConfig>	m_iterations;
   1693 };
   1694 
   1695 TextureBorderClampPerAxisCase2D::TextureBorderClampPerAxisCase2D (Context&							context,
   1696 																  const char*						name,
   1697 																  const char*						description,
   1698 																  deUint32							texFormat,
   1699 																  tcu::Sampler::DepthStencilMode	mode,
   1700 																  SizeType							sizeType,
   1701 																  deUint32							filter,
   1702 																  deUint32							texSWrap,
   1703 																  deUint32							texTWrap,
   1704 																  SamplingFunction					samplingFunction)
   1705 	: TextureBorderClampTest(context,
   1706 							 name,
   1707 							 description,
   1708 							 texFormat,
   1709 							 mode,
   1710 							 TextureBorderClampTest::STATE_TEXTURE_PARAM,
   1711 							 (sizeType == SIZE_POT) ? (16) : (7),
   1712 							 (sizeType == SIZE_POT) ? (8) : (9),
   1713 							 samplingFunction)
   1714 	, m_texSWrap			(texSWrap)
   1715 	, m_texTWrap			(texTWrap)
   1716 	, m_filter				(filter)
   1717 {
   1718 }
   1719 
   1720 void TextureBorderClampPerAxisCase2D::init (void)
   1721 {
   1722 	TextureBorderClampTest::init();
   1723 
   1724 	// \note TextureBorderClampTest::init() creates texture
   1725 	const tcu::TextureFormat		texFormat		= tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode);
   1726 	const tcu::TextureFormatInfo	texFormatInfo	= tcu::getTextureFormatInfo(texFormat);
   1727 
   1728 	IterationConfig iteration;
   1729 	iteration.p0			= tcu::Vec2(-0.25f, -0.75f);
   1730 	iteration.p1			= tcu::Vec2( 2.25f,  1.25f);
   1731 	iteration.borderColor	= mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.4f, 0.9f, 0.1f, 0.2f));
   1732 
   1733 	if (m_samplingFunction == SAMPLE_GATHER)
   1734 	{
   1735 		iteration.lookupScale	= tcu::Vec4(texFormatInfo.lookupScale.x());
   1736 		iteration.lookupBias	= tcu::Vec4(texFormatInfo.lookupBias.x());
   1737 	}
   1738 	else
   1739 	{
   1740 		iteration.lookupScale	= texFormatInfo.lookupScale;
   1741 		iteration.lookupBias	= texFormatInfo.lookupBias;
   1742 	}
   1743 
   1744 	iteration.minFilter		= m_filter;
   1745 	iteration.magFilter		= m_filter;
   1746 	iteration.sWrapMode		= m_texSWrap;
   1747 	iteration.tWrapMode		= m_texTWrap;
   1748 	iteration.compareMode	= GL_NONE;
   1749 	iteration.compareRef	= 0.0f;
   1750 
   1751 	m_iterations.push_back(iteration);
   1752 }
   1753 
   1754 int TextureBorderClampPerAxisCase2D::getNumIterations	(void) const
   1755 {
   1756 	return (int)m_iterations.size();
   1757 }
   1758 
   1759 TextureBorderClampTest::IterationConfig TextureBorderClampPerAxisCase2D::getIteration (int ndx) const
   1760 {
   1761 	return m_iterations[ndx];
   1762 }
   1763 
   1764 class TextureBorderClampDepthCompareCase : public TextureBorderClampTest
   1765 {
   1766 public:
   1767 									TextureBorderClampDepthCompareCase	(Context&			context,
   1768 																		 const char*		name,
   1769 																		 const char*		description,
   1770 																		 deUint32			texFormat,
   1771 																		 SizeType			sizeType,
   1772 																		 deUint32			filter,
   1773 																		 SamplingFunction	samplingFunction);
   1774 
   1775 private:
   1776 	void							init								(void);
   1777 
   1778 	int								getNumIterations					(void) const;
   1779 	IterationConfig					getIteration						(int ndx) const;
   1780 
   1781 	const deUint32					m_filter;
   1782 	std::vector<IterationConfig>	m_iterations;
   1783 };
   1784 
   1785 TextureBorderClampDepthCompareCase::TextureBorderClampDepthCompareCase (Context&			context,
   1786 																		const char*			name,
   1787 																		const char*			description,
   1788 																		deUint32			texFormat,
   1789 																		SizeType			sizeType,
   1790 																		deUint32			filter,
   1791 																		SamplingFunction	samplingFunction)
   1792 	: TextureBorderClampTest(context,
   1793 							 name,
   1794 							 description,
   1795 							 texFormat,
   1796 							 tcu::Sampler::MODE_DEPTH,
   1797 							 TextureBorderClampTest::STATE_TEXTURE_PARAM,
   1798 							 (sizeType == SIZE_POT) ? (32) : (13),
   1799 							 (sizeType == SIZE_POT) ? (16) : (17),
   1800 							 samplingFunction,
   1801 							 FLAG_USE_SHADOW_SAMPLER)
   1802 	, m_filter				(filter)
   1803 {
   1804 }
   1805 
   1806 void TextureBorderClampDepthCompareCase::init (void)
   1807 {
   1808 	TextureBorderClampTest::init();
   1809 
   1810 	// 0.5 <= 0.7
   1811 	{
   1812 		IterationConfig iteration;
   1813 		iteration.p0			= tcu::Vec2(-0.15f, -0.35f);
   1814 		iteration.p1			= tcu::Vec2( 1.25f,  1.1f);
   1815 		iteration.borderColor	= rr::GenericVec4(tcu::Vec4(0.7f, 0.0f, 0.0f, 0.0f));
   1816 		iteration.description	= "Border color in [0, 1] range";
   1817 		iteration.compareMode	= GL_LEQUAL;
   1818 		iteration.compareRef	= 0.5f;
   1819 		m_iterations.push_back(iteration);
   1820 	}
   1821 
   1822 	// 1.5 <= 1.0
   1823 	{
   1824 		IterationConfig iteration;
   1825 		iteration.p0			= tcu::Vec2(-0.15f, -0.35f);
   1826 		iteration.p1			= tcu::Vec2( 1.25f,  1.1f);
   1827 		iteration.borderColor	= rr::GenericVec4(tcu::Vec4(1.5f, 0.0f, 0.0f, 0.0f));
   1828 		iteration.description	= "Border color > 1, should be clamped";
   1829 		iteration.compareMode	= GL_LEQUAL;
   1830 		iteration.compareRef	= 1.0f;
   1831 		m_iterations.push_back(iteration);
   1832 	}
   1833 
   1834 	// -0.5 >= 0.0
   1835 	{
   1836 		IterationConfig iteration;
   1837 		iteration.p0			= tcu::Vec2(-0.15f, -0.35f);
   1838 		iteration.p1			= tcu::Vec2( 1.25f,  1.1f);
   1839 		iteration.borderColor	= rr::GenericVec4(tcu::Vec4(-0.5f, 0.0f, 0.0f, 0.0f));
   1840 		iteration.description	= "Border color < 0, should be clamped";
   1841 		iteration.compareMode	= GL_GEQUAL;
   1842 		iteration.compareRef	= 0.0f;
   1843 		m_iterations.push_back(iteration);
   1844 	}
   1845 
   1846 	// inf < 1.25
   1847 	{
   1848 		IterationConfig iteration;
   1849 		iteration.p0			= tcu::Vec2(-0.15f, -0.35f);
   1850 		iteration.p1			= tcu::Vec2( 1.25f,  1.1f);
   1851 		iteration.borderColor	= rr::GenericVec4(tcu::Vec4(std::numeric_limits<float>::infinity(), 0.0f, 0.0f, 0.0f));
   1852 		iteration.description	= "Border color == inf, should be clamped; ref > 1";
   1853 		iteration.compareMode	= GL_LESS;
   1854 		iteration.compareRef	= 1.25f;
   1855 		m_iterations.push_back(iteration);
   1856 	}
   1857 
   1858 	// -inf > -0.5
   1859 	{
   1860 		IterationConfig iteration;
   1861 		iteration.p0			= tcu::Vec2(-0.15f, -0.35f);
   1862 		iteration.p1			= tcu::Vec2( 1.25f,  1.1f);
   1863 		iteration.borderColor	= rr::GenericVec4(tcu::Vec4(-std::numeric_limits<float>::infinity(), 0.0f, 0.0f, 0.0f));
   1864 		iteration.description	= "Border color == inf, should be clamped; ref < 0";
   1865 		iteration.compareMode	= GL_GREATER;
   1866 		iteration.compareRef	= -0.5f;
   1867 		m_iterations.push_back(iteration);
   1868 	}
   1869 
   1870 	// common parameters
   1871 	for (int ndx = 0; ndx < (int)m_iterations.size(); ++ndx)
   1872 	{
   1873 		IterationConfig& iteration = m_iterations[ndx];
   1874 
   1875 		iteration.lookupScale	= tcu::Vec4(1.0);
   1876 		iteration.lookupBias	= tcu::Vec4(0.0);
   1877 		iteration.minFilter		= m_filter;
   1878 		iteration.magFilter		= m_filter;
   1879 		iteration.sWrapMode		= GL_CLAMP_TO_BORDER;
   1880 		iteration.tWrapMode		= GL_CLAMP_TO_BORDER;
   1881 	}
   1882 }
   1883 
   1884 int TextureBorderClampDepthCompareCase::getNumIterations	(void) const
   1885 {
   1886 	return (int)m_iterations.size();
   1887 }
   1888 
   1889 TextureBorderClampTest::IterationConfig TextureBorderClampDepthCompareCase::getIteration (int ndx) const
   1890 {
   1891 	return m_iterations[ndx];
   1892 }
   1893 
   1894 class TextureBorderClampUnusedChannelCase : public TextureBorderClampTest
   1895 {
   1896 public:
   1897 									TextureBorderClampUnusedChannelCase	(Context&						context,
   1898 																		 const char*					name,
   1899 																		 const char*					description,
   1900 																		 deUint32						texFormat,
   1901 																		 tcu::Sampler::DepthStencilMode	depthStencilMode);
   1902 
   1903 private:
   1904 	void							init								(void);
   1905 
   1906 	int								getNumIterations					(void) const;
   1907 	IterationConfig					getIteration						(int ndx) const;
   1908 
   1909 	std::vector<IterationConfig>	m_iterations;
   1910 };
   1911 
   1912 TextureBorderClampUnusedChannelCase::TextureBorderClampUnusedChannelCase (Context&							context,
   1913 																		  const char*						name,
   1914 																		  const char*						description,
   1915 																		  deUint32							texFormat,
   1916 																		  tcu::Sampler::DepthStencilMode	depthStencilMode)
   1917 	: TextureBorderClampTest(context,
   1918 							 name,
   1919 							 description,
   1920 							 texFormat,
   1921 							 depthStencilMode,
   1922 							 TextureBorderClampTest::STATE_TEXTURE_PARAM,
   1923 							 8,
   1924 							 8,
   1925 							 SAMPLE_FILTER)
   1926 {
   1927 }
   1928 
   1929 static rr::GenericVec4 selectComponents (const rr::GenericVec4& trueComponents, const rr::GenericVec4& falseComponents, const tcu::BVec4& m)
   1930 {
   1931 	return rr::GenericVec4(tcu::select(trueComponents.get<deUint32>(), falseComponents.get<deUint32>(), m));
   1932 }
   1933 
   1934 void TextureBorderClampUnusedChannelCase::init (void)
   1935 {
   1936 	TextureBorderClampTest::init();
   1937 
   1938 	// \note TextureBorderClampTest::init() creates texture
   1939 	const tcu::TextureFormat		texFormat			= tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode);
   1940 	const tcu::TextureFormatInfo	texFormatInfo		= tcu::getTextureFormatInfo(texFormat);
   1941 	const tcu::BVec4				channelMask			= tcu::getTextureFormatChannelMask(texFormat);
   1942 	const float						maxChannelValue		= (channelMask[0]) ? (texFormatInfo.valueMax[0])
   1943 														: (channelMask[1]) ? (texFormatInfo.valueMax[1])
   1944 														: (channelMask[2]) ? (texFormatInfo.valueMax[2])
   1945 														:                    (texFormatInfo.valueMax[3]);
   1946 
   1947 	const rr::GenericVec4			effectiveColors		= mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.6f));
   1948 	rr::GenericVec4					nonEffectiveColors;
   1949 
   1950 	switch (m_channelClass)
   1951 	{
   1952 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
   1953 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
   1954 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
   1955 			nonEffectiveColors = rr::GenericVec4(tcu::Vec4(maxChannelValue * 0.8f));
   1956 			break;
   1957 
   1958 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
   1959 			nonEffectiveColors = rr::GenericVec4(tcu::Vec4(maxChannelValue * 0.8f).cast<deInt32>());
   1960 			break;
   1961 
   1962 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
   1963 			nonEffectiveColors = rr::GenericVec4(tcu::Vec4(maxChannelValue * 0.8f).cast<deUint32>());
   1964 			break;
   1965 		default:
   1966 			DE_ASSERT(false);
   1967 	}
   1968 
   1969 	IterationConfig iteration;
   1970 	iteration.p0			= tcu::Vec2(-0.25f, -0.75f);
   1971 	iteration.p1			= tcu::Vec2( 2.25f,  1.25f);
   1972 	iteration.borderColor	= selectComponents(effectiveColors, nonEffectiveColors, channelMask);
   1973 	iteration.lookupScale	= texFormatInfo.lookupScale;
   1974 	iteration.lookupBias	= texFormatInfo.lookupBias;
   1975 	iteration.minFilter		= GL_NEAREST;
   1976 	iteration.magFilter		= GL_NEAREST;
   1977 	iteration.sWrapMode		= GL_CLAMP_TO_BORDER;
   1978 	iteration.tWrapMode		= GL_CLAMP_TO_BORDER;
   1979 	iteration.compareMode	= GL_NONE;
   1980 	iteration.compareRef	= 0.0f;
   1981 	iteration.description	= "Setting values to unused border color components";
   1982 
   1983 	m_iterations.push_back(iteration);
   1984 }
   1985 
   1986 int TextureBorderClampUnusedChannelCase::getNumIterations	(void) const
   1987 {
   1988 	return (int)m_iterations.size();
   1989 }
   1990 
   1991 TextureBorderClampTest::IterationConfig TextureBorderClampUnusedChannelCase::getIteration (int ndx) const
   1992 {
   1993 	return m_iterations[ndx];
   1994 }
   1995 
   1996 class TextureBorderClampPerAxisCase3D : public TestCase
   1997 {
   1998 public:
   1999 														TextureBorderClampPerAxisCase3D	(Context&		context,
   2000 																						 const char*	name,
   2001 																						 const char*	description,
   2002 																						 deUint32		texFormat,
   2003 																						 SizeType		size,
   2004 																						 deUint32		filter,
   2005 																						 deUint32		sWrap,
   2006 																						 deUint32		tWrap,
   2007 																						 deUint32		rWrap);
   2008 
   2009 private:
   2010 	void												init							(void);
   2011 	void												deinit							(void);
   2012 	IterateResult										iterate							(void);
   2013 
   2014 	void												renderTo						(tcu::Surface&									surface,
   2015 																						 const glu::TextureTestUtil::ReferenceParams&	samplerParams);
   2016 
   2017 	void												logParams						(const glu::TextureTestUtil::ReferenceParams&	samplerParams);
   2018 
   2019 	void												verifyImage						(const tcu::Surface&							image,
   2020 																						 const glu::TextureTestUtil::ReferenceParams&	samplerParams);
   2021 
   2022 	glu::TextureTestUtil::ReferenceParams				getSamplerParams				(void) const;
   2023 	deUint32											getCaseSeed						(void) const;
   2024 
   2025 	enum
   2026 	{
   2027 		VIEWPORT_WIDTH		= 128,
   2028 		VIEWPORT_HEIGHT		= 128,
   2029 	};
   2030 
   2031 	const deUint32										m_texFormat;
   2032 	const tcu::TextureChannelClass						m_channelClass;
   2033 	const tcu::IVec3									m_size;
   2034 	const deUint32										m_filter;
   2035 	const deUint32										m_sWrap;
   2036 	const deUint32										m_tWrap;
   2037 	const deUint32										m_rWrap;
   2038 
   2039 	de::MovePtr<glu::Texture3D>							m_texture;
   2040 	de::MovePtr<gls::TextureTestUtil::TextureRenderer>	m_renderer;
   2041 
   2042 	rr::GenericVec4										m_borderColor;
   2043 	std::vector<float>									m_texCoords;
   2044 	tcu::Vec4											m_lookupScale;
   2045 	tcu::Vec4											m_lookupBias;
   2046 };
   2047 
   2048 TextureBorderClampPerAxisCase3D::TextureBorderClampPerAxisCase3D (Context&		context,
   2049 																  const char*	name,
   2050 																  const char*	description,
   2051 																  deUint32		texFormat,
   2052 																  SizeType		size,
   2053 																  deUint32		filter,
   2054 																  deUint32		sWrap,
   2055 																  deUint32		tWrap,
   2056 																  deUint32		rWrap)
   2057 	: TestCase			(context, name, description)
   2058 	, m_texFormat		(texFormat)
   2059 	, m_channelClass	(getFormatChannelClass(texFormat, tcu::Sampler::MODE_LAST))
   2060 	, m_size			((size == SIZE_POT) ? (tcu::IVec3(8, 16, 4)) : (tcu::IVec3(13, 5, 7)))
   2061 	, m_filter			(filter)
   2062 	, m_sWrap			(sWrap)
   2063 	, m_tWrap			(tWrap)
   2064 	, m_rWrap			(rWrap)
   2065 {
   2066 }
   2067 
   2068 void TextureBorderClampPerAxisCase3D::init (void)
   2069 {
   2070 	const bool				supportsES32	= glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
   2071 	const glu::GLSLVersion	glslVersion		= glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType());
   2072 
   2073 	if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_border_clamp"))
   2074 		throw tcu::NotSupportedError("Test requires GL_EXT_texture_border_clamp extension");
   2075 
   2076 	if (glu::isCompressedFormat(m_texFormat)													&&
   2077 		!supportsES32																			&&
   2078 		tcu::isAstcFormat(glu::mapGLCompressedTexFormat(m_texFormat))							&&
   2079 		!m_context.getContextInfo().isExtensionSupported("GL_KHR_texture_compression_astc_ldr"))
   2080 	{
   2081 		throw tcu::NotSupportedError("Test requires GL_KHR_texture_compression_astc_ldr extension");
   2082 	}
   2083 	if (m_texFormat == GL_BGRA && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_format_BGRA8888"))
   2084 		throw tcu::NotSupportedError("Test requires GL_EXT_texture_format_BGRA8888 extension");
   2085 	if (m_context.getRenderTarget().getWidth() < VIEWPORT_WIDTH ||
   2086 		m_context.getRenderTarget().getHeight() < VIEWPORT_HEIGHT)
   2087 	{
   2088 		throw tcu::NotSupportedError("Test requires " + de::toString<int>(VIEWPORT_WIDTH) + "x" + de::toString<int>(VIEWPORT_HEIGHT) + " viewport");
   2089 	}
   2090 
   2091 	// resources
   2092 	m_texture = genDummyTexture<glu::Texture3D>(m_context.getRenderContext(), m_context.getContextInfo(), m_texFormat, m_size);
   2093 	m_renderer = de::MovePtr<gls::TextureTestUtil::TextureRenderer>(new gls::TextureTestUtil::TextureRenderer(m_context.getRenderContext(), m_testCtx.getLog(), glslVersion, glu::PRECISION_HIGHP));
   2094 
   2095 	// texture info
   2096 	m_testCtx.getLog()	<< tcu::TestLog::Message
   2097 						<< "Created 3D texture with format " << glu::getTextureFormatName(m_texFormat)
   2098 						<< ", size (" << m_texture->getRefTexture().getWidth() << ", " << m_texture->getRefTexture().getHeight() << ", " << m_texture->getRefTexture().getDepth() << ")\n"
   2099 						<< tcu::TestLog::EndMessage;
   2100 
   2101 	// tex coord
   2102 	{
   2103 		m_testCtx.getLog()	<< tcu::TestLog::Message
   2104 							<< "Setting tex coords bottom-left: (-1, -1, -1.5), top-right (2, 2, 2.5)\n"
   2105 							<< tcu::TestLog::EndMessage;
   2106 
   2107 		m_texCoords.resize(4*3);
   2108 
   2109 		m_texCoords[0] = -1.0f; m_texCoords[ 1] = -1.0f; m_texCoords[ 2] = -1.5f;
   2110 		m_texCoords[3] = -1.0f; m_texCoords[ 4] =  2.0f; m_texCoords[ 5] = 0.5f;
   2111 		m_texCoords[6] =  2.0f; m_texCoords[ 7] = -1.0f; m_texCoords[ 8] = 0.5f;
   2112 		m_texCoords[9] =  2.0f; m_texCoords[10] =  2.0f; m_texCoords[11] =  2.5f;
   2113 	}
   2114 
   2115 	// set render params
   2116 	{
   2117 		const tcu::TextureFormat		texFormat		= m_texture->getRefTexture().getFormat();
   2118 		const tcu::TextureFormatInfo	texFormatInfo	= tcu::getTextureFormatInfo(texFormat);
   2119 
   2120 		m_borderColor	= mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.2f, 0.6f, 0.9f, 0.4f));
   2121 
   2122 		m_lookupScale	= texFormatInfo.lookupScale;
   2123 		m_lookupBias	= texFormatInfo.lookupBias;
   2124 	}
   2125 }
   2126 
   2127 void TextureBorderClampPerAxisCase3D::deinit (void)
   2128 {
   2129 	m_texture.clear();
   2130 	m_renderer.clear();
   2131 }
   2132 
   2133 TextureBorderClampPerAxisCase3D::IterateResult TextureBorderClampPerAxisCase3D::iterate (void)
   2134 {
   2135 	tcu::Surface								renderedFrame		(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
   2136 	const glu::TextureTestUtil::ReferenceParams	samplerParams		= getSamplerParams();
   2137 
   2138 	logParams(samplerParams);
   2139 	renderTo(renderedFrame, samplerParams);
   2140 	verifyImage(renderedFrame, samplerParams);
   2141 
   2142 	return STOP;
   2143 }
   2144 
   2145 void TextureBorderClampPerAxisCase3D::logParams (const glu::TextureTestUtil::ReferenceParams& samplerParams)
   2146 {
   2147 	const std::string	borderColorString	= (m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)   ? (de::toString(m_borderColor.get<deInt32>()))
   2148 											: (m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) ? (de::toString(m_borderColor.get<deUint32>()))
   2149 											:																  (de::toString(m_borderColor.get<float>()));
   2150 
   2151 	m_testCtx.getLog()	<< tcu::TestLog::Message
   2152 						<< "Border color is " << borderColorString << "\n"
   2153 						<< "Texture lookup bias: " << samplerParams.colorBias << "\n"
   2154 						<< "Texture lookup scale: " << samplerParams.colorScale << "\n"
   2155 						<< "Filter: " << glu::getTextureFilterName(m_filter) << "\n"
   2156 						<< "Wrap mode: s = " << glu::getRepeatModeStr(m_sWrap)
   2157 							<< ", t = " << glu::getRepeatModeStr(m_tWrap)
   2158 							<< ", r = " << glu::getRepeatModeStr(m_rWrap) << "\n"
   2159 						<< tcu::TestLog::EndMessage;
   2160 }
   2161 
   2162 void TextureBorderClampPerAxisCase3D::renderTo (tcu::Surface&									surface,
   2163 												const glu::TextureTestUtil::ReferenceParams&	samplerParams)
   2164 {
   2165 	const glw::Functions&						gl			= m_context.getRenderContext().getFunctions();
   2166 	const gls::TextureTestUtil::RandomViewport	viewport	(m_context.getRenderTarget(), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, getCaseSeed());
   2167 
   2168 	// Bind to unit 0.
   2169 	gl.activeTexture(GL_TEXTURE0);
   2170 	gl.bindTexture(GL_TEXTURE_3D, m_texture->getGLTexture());
   2171 
   2172 	// Setup filtering and wrap modes.
   2173 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S,		glu::getGLWrapMode(samplerParams.sampler.wrapS));
   2174 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T,		glu::getGLWrapMode(samplerParams.sampler.wrapT));
   2175 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R,		glu::getGLWrapMode(samplerParams.sampler.wrapR));
   2176 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER,	glu::getGLFilterMode(samplerParams.sampler.minFilter));
   2177 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER,	glu::getGLFilterMode(samplerParams.sampler.magFilter));
   2178 
   2179 	switch (m_channelClass)
   2180 	{
   2181 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
   2182 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
   2183 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
   2184 			gl.texParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, m_borderColor.getAccess<float>());
   2185 			break;
   2186 
   2187 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
   2188 			gl.texParameterIiv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, m_borderColor.getAccess<deInt32>());
   2189 			break;
   2190 
   2191 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
   2192 			gl.texParameterIuiv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, m_borderColor.getAccess<deUint32>());
   2193 			break;
   2194 
   2195 		default:
   2196 			DE_ASSERT(false);
   2197 	}
   2198 
   2199 	GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
   2200 
   2201 	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
   2202 	m_renderer->renderQuad(0, &m_texCoords[0], samplerParams);
   2203 	glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, surface.getAccess());
   2204 }
   2205 
   2206 void TextureBorderClampPerAxisCase3D::verifyImage (const tcu::Surface&							renderedFrame,
   2207 												   const glu::TextureTestUtil::ReferenceParams&	samplerParams)
   2208 {
   2209 	const tcu::PixelFormat			pixelFormat			= m_context.getRenderTarget().getPixelFormat();
   2210 	const int						colorErrorBits		= 2;
   2211 	const tcu::IVec4				colorBits			= tcu::max(glu::TextureTestUtil::getBitsVec(pixelFormat) - tcu::IVec4(colorErrorBits), tcu::IVec4(0));
   2212 	tcu::Surface					reference			(renderedFrame.getWidth(), renderedFrame.getHeight());
   2213 	tcu::Surface					errorMask			(renderedFrame.getWidth(), renderedFrame.getHeight());
   2214 	tcu::LodPrecision				lodPrecision;
   2215 	tcu::LookupPrecision			lookupPrecision;
   2216 	int								numFailedPixels;
   2217 
   2218 	lodPrecision.derivateBits		= 18;
   2219 	lodPrecision.lodBits			= 5;
   2220 
   2221 	lookupPrecision.colorThreshold	= tcu::computeFixedPointThreshold(colorBits) / samplerParams.colorScale;
   2222 	lookupPrecision.coordBits		= tcu::IVec3(20,20,0);
   2223 	lookupPrecision.uvwBits			= tcu::IVec3(5,5,0);
   2224 	lookupPrecision.colorMask		= glu::TextureTestUtil::getCompareMask(pixelFormat);
   2225 
   2226 	glu::TextureTestUtil::sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), m_texture->getRefTexture(), &m_texCoords[0], samplerParams);
   2227 
   2228 	numFailedPixels = glu::TextureTestUtil::computeTextureLookupDiff(renderedFrame.getAccess(), reference.getAccess(), errorMask.getAccess(), m_texture->getRefTexture(),
   2229 																	 &m_texCoords[0], samplerParams, lookupPrecision, lodPrecision, m_testCtx.getWatchDog());
   2230 
   2231 	if (numFailedPixels > 0)
   2232 		m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
   2233 	m_testCtx.getLog()	<< tcu::TestLog::ImageSet("VerifyResult", "Verification result")
   2234 						<< tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame);
   2235 	if (numFailedPixels > 0)
   2236 	{
   2237 		m_testCtx.getLog()	<< tcu::TestLog::Image("Reference", "Ideal reference image", reference)
   2238 							<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
   2239 	}
   2240 	m_testCtx.getLog() << tcu::TestLog::EndImageSet;
   2241 
   2242 	if (numFailedPixels == 0)
   2243 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   2244 	else
   2245 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
   2246 }
   2247 
   2248 glu::TextureTestUtil::ReferenceParams TextureBorderClampPerAxisCase3D::getSamplerParams (void) const
   2249 {
   2250 	const tcu::TextureFormat				texFormat		= m_texture->getRefTexture().getFormat();
   2251 	glu::TextureTestUtil::ReferenceParams	refParams		(glu::TextureTestUtil::TEXTURETYPE_3D);
   2252 
   2253 	refParams.sampler					= glu::mapGLSampler(m_sWrap, m_tWrap, m_rWrap, m_filter, m_filter);
   2254 	refParams.sampler.borderColor		= m_borderColor;
   2255 	refParams.lodMode					= glu::TextureTestUtil::LODMODE_EXACT;
   2256 	refParams.samplerType				= glu::TextureTestUtil::getSamplerType(texFormat);
   2257 	refParams.colorScale				= m_lookupScale;
   2258 	refParams.colorBias					= m_lookupBias;
   2259 
   2260 	return refParams;
   2261 }
   2262 
   2263 deUint32 TextureBorderClampPerAxisCase3D::getCaseSeed (void) const
   2264 {
   2265 	tcu::SeedBuilder builder;
   2266 	builder	<< std::string(getName())
   2267 			<< m_texFormat
   2268 			<< m_filter
   2269 			<< m_sWrap
   2270 			<< m_tWrap
   2271 			<< m_rWrap
   2272 			<< m_texture->getRefTexture().getWidth()
   2273 			<< m_texture->getRefTexture().getHeight()
   2274 			<< m_texture->getRefTexture().getDepth();
   2275 	return builder.get();
   2276 }
   2277 
   2278 } // anonymous
   2279 
   2280 TextureBorderClampTests::TextureBorderClampTests (Context& context)
   2281 	: TestCaseGroup(context, "border_clamp", "EXT_texture_border_clamp tests")
   2282 {
   2283 }
   2284 
   2285 TextureBorderClampTests::~TextureBorderClampTests (void)
   2286 {
   2287 }
   2288 
   2289 void TextureBorderClampTests::init (void)
   2290 {
   2291 	static const struct
   2292 	{
   2293 		const char*									name;
   2294 		deUint32									filter;
   2295 		TextureBorderClampTest::SamplingFunction	sampling;
   2296 	} s_filters[] =
   2297 	{
   2298 		{ "nearest",	GL_NEAREST,	TextureBorderClampTest::SAMPLE_FILTER	},
   2299 		{ "linear",		GL_LINEAR,	TextureBorderClampTest::SAMPLE_FILTER	},
   2300 		{ "gather",		GL_NEAREST,	TextureBorderClampTest::SAMPLE_GATHER	},
   2301 	};
   2302 
   2303 	// .formats
   2304 	{
   2305 		static const struct
   2306 		{
   2307 			const char*						name;
   2308 			deUint32						format;
   2309 			tcu::Sampler::DepthStencilMode	mode;
   2310 		} formats[] =
   2311 		{
   2312 			{ "luminance",									GL_LUMINANCE,									tcu::Sampler::MODE_LAST		},
   2313 			{ "alpha",										GL_ALPHA,										tcu::Sampler::MODE_LAST		},
   2314 			{ "luminance_alpha",							GL_LUMINANCE_ALPHA,								tcu::Sampler::MODE_LAST		},
   2315 			{ "bgra",										GL_BGRA,										tcu::Sampler::MODE_LAST		},
   2316 			{ "r8",											GL_R8,											tcu::Sampler::MODE_LAST		},
   2317 			{ "r8_snorm",									GL_R8_SNORM,									tcu::Sampler::MODE_LAST		},
   2318 			{ "rg8",										GL_RG8,											tcu::Sampler::MODE_LAST		},
   2319 			{ "rg8_snorm",									GL_RG8_SNORM,									tcu::Sampler::MODE_LAST		},
   2320 			{ "rgb8",										GL_RGB8,										tcu::Sampler::MODE_LAST		},
   2321 			{ "rgb8_snorm",									GL_RGB8_SNORM,									tcu::Sampler::MODE_LAST		},
   2322 			{ "rgb565",										GL_RGB565,										tcu::Sampler::MODE_LAST		},
   2323 			{ "rgba4",										GL_RGBA4,										tcu::Sampler::MODE_LAST		},
   2324 			{ "rgb5_a1",									GL_RGB5_A1,										tcu::Sampler::MODE_LAST		},
   2325 			{ "rgba8",										GL_RGBA8,										tcu::Sampler::MODE_LAST		},
   2326 			{ "rgba8_snorm",								GL_RGBA8_SNORM,									tcu::Sampler::MODE_LAST		},
   2327 			{ "rgb10_a2",									GL_RGB10_A2,									tcu::Sampler::MODE_LAST		},
   2328 			{ "rgb10_a2ui",									GL_RGB10_A2UI,									tcu::Sampler::MODE_LAST		},
   2329 			{ "srgb8",										GL_SRGB8,										tcu::Sampler::MODE_LAST		},
   2330 			{ "srgb8_alpha8",								GL_SRGB8_ALPHA8,								tcu::Sampler::MODE_LAST		},
   2331 			{ "r16f",										GL_R16F,										tcu::Sampler::MODE_LAST		},
   2332 			{ "rg16f",										GL_RG16F,										tcu::Sampler::MODE_LAST		},
   2333 			{ "rgb16f",										GL_RGB16F,										tcu::Sampler::MODE_LAST		},
   2334 			{ "rgba16f",									GL_RGBA16F,										tcu::Sampler::MODE_LAST		},
   2335 			{ "r32f",										GL_R32F,										tcu::Sampler::MODE_LAST		},
   2336 			{ "rg32f",										GL_RG32F,										tcu::Sampler::MODE_LAST		},
   2337 			{ "rgb32f",										GL_RGB32F,										tcu::Sampler::MODE_LAST		},
   2338 			{ "rgba32f",									GL_RGBA32F,										tcu::Sampler::MODE_LAST		},
   2339 			{ "r11f_g11f_b10f",								GL_R11F_G11F_B10F,								tcu::Sampler::MODE_LAST		},
   2340 			{ "rgb9_e5",									GL_RGB9_E5,										tcu::Sampler::MODE_LAST		},
   2341 			{ "r8i",										GL_R8I,											tcu::Sampler::MODE_LAST		},
   2342 			{ "r8ui",										GL_R8UI,										tcu::Sampler::MODE_LAST		},
   2343 			{ "r16i",										GL_R16I,										tcu::Sampler::MODE_LAST		},
   2344 			{ "r16ui",										GL_R16UI,										tcu::Sampler::MODE_LAST		},
   2345 			{ "r32i",										GL_R32I,										tcu::Sampler::MODE_LAST		},
   2346 			{ "r32ui",										GL_R32UI,										tcu::Sampler::MODE_LAST		},
   2347 			{ "rg8i",										GL_RG8I,										tcu::Sampler::MODE_LAST		},
   2348 			{ "rg8ui",										GL_RG8UI,										tcu::Sampler::MODE_LAST		},
   2349 			{ "rg16i",										GL_RG16I,										tcu::Sampler::MODE_LAST		},
   2350 			{ "rg16ui",										GL_RG16UI,										tcu::Sampler::MODE_LAST		},
   2351 			{ "rg32i",										GL_RG32I,										tcu::Sampler::MODE_LAST		},
   2352 			{ "rg32ui",										GL_RG32UI,										tcu::Sampler::MODE_LAST		},
   2353 			{ "rgb8i",										GL_RGB8I,										tcu::Sampler::MODE_LAST		},
   2354 			{ "rgb8ui",										GL_RGB8UI,										tcu::Sampler::MODE_LAST		},
   2355 			{ "rgb16i",										GL_RGB16I,										tcu::Sampler::MODE_LAST		},
   2356 			{ "rgb16ui",									GL_RGB16UI,										tcu::Sampler::MODE_LAST		},
   2357 			{ "rgb32i",										GL_RGB32I,										tcu::Sampler::MODE_LAST		},
   2358 			{ "rgb32ui",									GL_RGB32UI,										tcu::Sampler::MODE_LAST		},
   2359 			{ "rgba8i",										GL_RGBA8I,										tcu::Sampler::MODE_LAST		},
   2360 			{ "rgba8ui",									GL_RGBA8UI,										tcu::Sampler::MODE_LAST		},
   2361 			{ "rgba16i",									GL_RGBA16I,										tcu::Sampler::MODE_LAST		},
   2362 			{ "rgba16ui",									GL_RGBA16UI,									tcu::Sampler::MODE_LAST		},
   2363 			{ "rgba32i",									GL_RGBA32I,										tcu::Sampler::MODE_LAST		},
   2364 			{ "rgba32ui",									GL_RGBA32UI,									tcu::Sampler::MODE_LAST		},
   2365 			{ "depth_component16",							GL_DEPTH_COMPONENT16,							tcu::Sampler::MODE_DEPTH	},
   2366 			{ "depth_component24",							GL_DEPTH_COMPONENT24,							tcu::Sampler::MODE_DEPTH	},
   2367 			{ "depth_component32f",							GL_DEPTH_COMPONENT32F,							tcu::Sampler::MODE_DEPTH	},
   2368 			{ "stencil_index8",								GL_STENCIL_INDEX8,								tcu::Sampler::MODE_STENCIL	},
   2369 			{ "depth24_stencil8_sample_depth",				GL_DEPTH24_STENCIL8,							tcu::Sampler::MODE_DEPTH	},
   2370 			{ "depth32f_stencil8_sample_depth",				GL_DEPTH32F_STENCIL8,							tcu::Sampler::MODE_DEPTH	},
   2371 			{ "depth24_stencil8_sample_stencil",			GL_DEPTH24_STENCIL8,							tcu::Sampler::MODE_STENCIL	},
   2372 			{ "depth32f_stencil8_sample_stencil",			GL_DEPTH32F_STENCIL8,							tcu::Sampler::MODE_STENCIL	},
   2373 			{ "compressed_r11_eac",							GL_COMPRESSED_R11_EAC,							tcu::Sampler::MODE_LAST		},
   2374 			{ "compressed_signed_r11_eac",					GL_COMPRESSED_SIGNED_R11_EAC,					tcu::Sampler::MODE_LAST		},
   2375 			{ "compressed_rg11_eac",						GL_COMPRESSED_RG11_EAC,							tcu::Sampler::MODE_LAST		},
   2376 			{ "compressed_signed_rg11_eac",					GL_COMPRESSED_SIGNED_RG11_EAC,					tcu::Sampler::MODE_LAST		},
   2377 			{ "compressed_rgb8_etc2",						GL_COMPRESSED_RGB8_ETC2,						tcu::Sampler::MODE_LAST		},
   2378 			{ "compressed_srgb8_etc2",						GL_COMPRESSED_SRGB8_ETC2,						tcu::Sampler::MODE_LAST		},
   2379 			{ "compressed_rgb8_punchthrough_alpha1_etc2",	GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,	tcu::Sampler::MODE_LAST		},
   2380 			{ "compressed_srgb8_punchthrough_alpha1_etc2",	GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,	tcu::Sampler::MODE_LAST		},
   2381 			{ "compressed_rgba8_etc2_eac",					GL_COMPRESSED_RGBA8_ETC2_EAC,					tcu::Sampler::MODE_LAST		},
   2382 			{ "compressed_srgb8_alpha8_etc2_eac",			GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,			tcu::Sampler::MODE_LAST		},
   2383 		};
   2384 
   2385 		tcu::TestCaseGroup* const formatsGroup = new tcu::TestCaseGroup(m_testCtx, "formats", "Format tests");
   2386 		addChild(formatsGroup);
   2387 
   2388 		// .format
   2389 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
   2390 		{
   2391 			const deUint32							format			= formats[formatNdx].format;
   2392 			const tcu::Sampler::DepthStencilMode	sampleMode		= formats[formatNdx].mode;
   2393 			const bool								isCompressed	= glu::isCompressedFormat(format);
   2394 			const bool								coreFilterable	= isCoreFilterableFormat(format, sampleMode);
   2395 			tcu::TestCaseGroup* const				formatGroup		= new tcu::TestCaseGroup(m_testCtx, formats[formatNdx].name, "Format test");
   2396 
   2397 			formatsGroup->addChild(formatGroup);
   2398 
   2399 			// .nearest
   2400 			// .linear
   2401 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx)
   2402 			{
   2403 				// [not-compressed]
   2404 				// .size_pot
   2405 				// .size_npot
   2406 				// [compressed]
   2407 				// .size_tile_multiple (also pot)
   2408 				// .size_not_tile_multiple (also npot)
   2409 				for (int sizeNdx = 0; sizeNdx < 2; ++sizeNdx)
   2410 				{
   2411 					const bool				isNpotCase		= (sizeNdx == 1);
   2412 					const char* const		sizePotName		= (!isCompressed) ? ("size_pot") : ("size_tile_multiple");
   2413 					const char* const		sizeNpotName	= (!isCompressed) ? ("size_npot") : ("size_not_tile_multiple");
   2414 					const char* const		sizeName		= (isNpotCase) ? (sizeNpotName) : (sizePotName);
   2415 					const SizeType			sizeType		= (isNpotCase) ? (SIZE_NPOT) : (SIZE_POT);
   2416 					const std::string		caseName		= std::string() + s_filters[filterNdx].name + "_" + sizeName;
   2417 					const deUint32			filter			= s_filters[filterNdx].filter;
   2418 
   2419 					if (coreFilterable || !filterRequiresFilterability(filter))
   2420 						formatGroup->addChild(new TextureBorderClampFormatCase(m_context,
   2421 																			   caseName.c_str(),
   2422 																			   "",
   2423 																			   format,
   2424 																			   sampleMode,
   2425 																			   TextureBorderClampFormatCase::STATE_TEXTURE_PARAM,
   2426 																			   sizeType,
   2427 																			   filter,
   2428 																			   s_filters[filterNdx].sampling));
   2429 				}
   2430 			}
   2431 		}
   2432 	}
   2433 
   2434 	// .range_clamp
   2435 	{
   2436 		static const struct
   2437 		{
   2438 			const char*						name;
   2439 			deUint32						format;
   2440 			tcu::Sampler::DepthStencilMode	mode;
   2441 		} formats[] =
   2442 		{
   2443 			{ "unorm_color",								GL_R8,					tcu::Sampler::MODE_LAST		},
   2444 			{ "snorm_color",								GL_R8_SNORM,			tcu::Sampler::MODE_LAST		},
   2445 			{ "float_color",								GL_RG32F,				tcu::Sampler::MODE_LAST		},
   2446 			{ "int_color",									GL_R8I,					tcu::Sampler::MODE_LAST		},
   2447 			{ "uint_color",									GL_R16UI,				tcu::Sampler::MODE_LAST		},
   2448 			{ "srgb_color",									GL_SRGB8_ALPHA8,		tcu::Sampler::MODE_LAST		},
   2449 			{ "unorm_depth",								GL_DEPTH_COMPONENT24,	tcu::Sampler::MODE_DEPTH	},
   2450 			{ "float_depth",								GL_DEPTH_COMPONENT32F,	tcu::Sampler::MODE_DEPTH	},
   2451 			{ "uint_stencil",								GL_STENCIL_INDEX8,		tcu::Sampler::MODE_STENCIL	},
   2452 			{ "float_depth_uint_stencil_sample_depth",		GL_DEPTH32F_STENCIL8,	tcu::Sampler::MODE_DEPTH	},
   2453 			{ "float_depth_uint_stencil_sample_stencil",	GL_DEPTH32F_STENCIL8,	tcu::Sampler::MODE_STENCIL	},
   2454 			{ "unorm_depth_uint_stencil_sample_depth",		GL_DEPTH24_STENCIL8,	tcu::Sampler::MODE_DEPTH	},
   2455 			{ "unorm_depth_uint_stencil_sample_stencil",	GL_DEPTH24_STENCIL8,	tcu::Sampler::MODE_STENCIL	},
   2456 			{ "compressed_color",							GL_COMPRESSED_RG11_EAC,	tcu::Sampler::MODE_LAST		},
   2457 		};
   2458 
   2459 		tcu::TestCaseGroup* const rangeClampGroup = new tcu::TestCaseGroup(m_testCtx, "range_clamp", "Range clamp tests");
   2460 		addChild(rangeClampGroup);
   2461 
   2462 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
   2463 		for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx)
   2464 		{
   2465 			const deUint32							format			= formats[formatNdx].format;
   2466 			const tcu::Sampler::DepthStencilMode	sampleMode		= formats[formatNdx].mode;
   2467 			const std::string						caseName		= std::string() + s_filters[filterNdx].name + "_" + formats[formatNdx].name;
   2468 			const deUint32							filter			= s_filters[filterNdx].filter;
   2469 			const bool								coreFilterable	= isCoreFilterableFormat(format, sampleMode);
   2470 
   2471 			if (s_filters[filterNdx].sampling == TextureBorderClampTest::SAMPLE_GATHER)
   2472 				continue;
   2473 
   2474 			if (coreFilterable || !filterRequiresFilterability(filter))
   2475 				rangeClampGroup->addChild(new TextureBorderClampRangeClampCase(m_context, caseName.c_str(), "", format, sampleMode, filter));
   2476 		}
   2477 	}
   2478 
   2479 	// .sampler
   2480 	{
   2481 		static const struct
   2482 		{
   2483 			const char*						name;
   2484 			deUint32						format;
   2485 			tcu::Sampler::DepthStencilMode	mode;
   2486 		} formats[] =
   2487 		{
   2488 			{ "unorm_color",		GL_R8,					tcu::Sampler::MODE_LAST		},
   2489 			{ "snorm_color",		GL_R8_SNORM,			tcu::Sampler::MODE_LAST		},
   2490 			{ "float_color",		GL_RG32F,				tcu::Sampler::MODE_LAST		},
   2491 			{ "int_color",			GL_R8I,					tcu::Sampler::MODE_LAST		},
   2492 			{ "uint_color",			GL_R16UI,				tcu::Sampler::MODE_LAST		},
   2493 			{ "unorm_depth",		GL_DEPTH_COMPONENT24,	tcu::Sampler::MODE_DEPTH	},
   2494 			{ "float_depth",		GL_DEPTH_COMPONENT32F,	tcu::Sampler::MODE_DEPTH	},
   2495 			{ "uint_stencil",		GL_STENCIL_INDEX8,		tcu::Sampler::MODE_STENCIL	},
   2496 			{ "compressed_color",	GL_COMPRESSED_RG11_EAC,	tcu::Sampler::MODE_LAST		},
   2497 		};
   2498 
   2499 		tcu::TestCaseGroup* const samplerGroup = new tcu::TestCaseGroup(m_testCtx, "sampler", "Sampler param tests");
   2500 		addChild(samplerGroup);
   2501 
   2502 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
   2503 		{
   2504 			const deUint32							format		= formats[formatNdx].format;
   2505 			const tcu::Sampler::DepthStencilMode	sampleMode	= formats[formatNdx].mode;
   2506 			const char*								caseName	= formats[formatNdx].name;
   2507 
   2508 			samplerGroup->addChild(new TextureBorderClampFormatCase(m_context,
   2509 																	caseName,
   2510 																	"",
   2511 																	format,
   2512 																	sampleMode,
   2513 																	TextureBorderClampFormatCase::STATE_SAMPLER_PARAM,
   2514 																	SIZE_POT,
   2515 																	GL_NEAREST,
   2516 																	TextureBorderClampFormatCase::SAMPLE_FILTER));
   2517 		}
   2518 	}
   2519 
   2520 	// .per_axis_wrap_mode
   2521 	{
   2522 		static const struct
   2523 		{
   2524 			const char*						name;
   2525 			bool							is3D;
   2526 		} targets[] =
   2527 		{
   2528 			{ "texture_2d", false	},
   2529 			{ "texture_3d", true	},
   2530 		};
   2531 		static const struct
   2532 		{
   2533 			const char*						name;
   2534 			deUint32						format;
   2535 			tcu::Sampler::DepthStencilMode	mode;
   2536 			bool							supports3D;
   2537 		} formats[] =
   2538 		{
   2539 			{ "unorm_color",		GL_RG8,						tcu::Sampler::MODE_LAST,	true	},
   2540 			{ "snorm_color",		GL_RG8_SNORM,				tcu::Sampler::MODE_LAST,	true	},
   2541 			{ "float_color",		GL_R32F,					tcu::Sampler::MODE_LAST,	true	},
   2542 			{ "int_color",			GL_RG16I,					tcu::Sampler::MODE_LAST,	true	},
   2543 			{ "uint_color",			GL_R8UI,					tcu::Sampler::MODE_LAST,	true	},
   2544 			{ "unorm_depth",		GL_DEPTH_COMPONENT16,		tcu::Sampler::MODE_DEPTH,	false	},
   2545 			{ "float_depth",		GL_DEPTH32F_STENCIL8,		tcu::Sampler::MODE_DEPTH,	false	},
   2546 			{ "uint_stencil",		GL_DEPTH32F_STENCIL8,		tcu::Sampler::MODE_STENCIL,	false	},
   2547 			{ "compressed_color",	GL_COMPRESSED_RGB8_ETC2,	tcu::Sampler::MODE_LAST,	false	},
   2548 		};
   2549 		static const struct
   2550 		{
   2551 			const char*	name;
   2552 			deUint32	sWrap;
   2553 			deUint32	tWrap;
   2554 			deUint32	rWrap;
   2555 			bool		is3D;
   2556 		} wrapConfigs[] =
   2557 		{
   2558 			// 2d configs
   2559 			{ "s_clamp_to_edge_t_clamp_to_border",						GL_CLAMP_TO_EDGE,	GL_CLAMP_TO_BORDER,	GL_NONE,			false	},
   2560 			{ "s_repeat_t_clamp_to_border",								GL_REPEAT,			GL_CLAMP_TO_BORDER,	GL_NONE,			false	},
   2561 			{ "s_mirrored_repeat_t_clamp_to_border",					GL_MIRRORED_REPEAT,	GL_CLAMP_TO_BORDER,	GL_NONE,			false	},
   2562 
   2563 			// 3d configs
   2564 			{ "s_clamp_to_border_t_clamp_to_border_r_clamp_to_border",	GL_CLAMP_TO_BORDER,	GL_CLAMP_TO_BORDER,	GL_CLAMP_TO_BORDER,	true	},
   2565 			{ "s_clamp_to_border_t_clamp_to_border_r_repeat",			GL_CLAMP_TO_BORDER,	GL_CLAMP_TO_BORDER,	GL_REPEAT,			true	},
   2566 			{ "s_mirrored_repeat_t_clamp_to_border_r_repeat",			GL_MIRRORED_REPEAT,	GL_CLAMP_TO_BORDER,	GL_REPEAT,			true	},
   2567 			{ "s_repeat_t_mirrored_repeat_r_clamp_to_border",			GL_REPEAT,			GL_MIRRORED_REPEAT,	GL_CLAMP_TO_BORDER,	true	},
   2568 		};
   2569 
   2570 		tcu::TestCaseGroup* const perAxisGroup = new tcu::TestCaseGroup(m_testCtx, "per_axis_wrap_mode", "Per-axis wrapping modes");
   2571 		addChild(perAxisGroup);
   2572 
   2573 		// .texture_nd
   2574 		for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
   2575 		{
   2576 			tcu::TestCaseGroup* const targetGroup = new tcu::TestCaseGroup(m_testCtx, targets[targetNdx].name, "Texture target test");
   2577 			perAxisGroup->addChild(targetGroup);
   2578 
   2579 			// .format
   2580 			for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
   2581 			{
   2582 				if (targets[targetNdx].is3D && !formats[formatNdx].supports3D)
   2583 					continue;
   2584 				else
   2585 				{
   2586 					const deUint32							format			= formats[formatNdx].format;
   2587 					const tcu::Sampler::DepthStencilMode	sampleMode		= formats[formatNdx].mode;
   2588 					const bool								coreFilterable	= isCoreFilterableFormat(format, sampleMode);
   2589 					tcu::TestCaseGroup* const				formatGroup		= new tcu::TestCaseGroup(m_testCtx, formats[formatNdx].name, "Format test");
   2590 					targetGroup->addChild(formatGroup);
   2591 
   2592 					// .linear
   2593 					// .nearest
   2594 					// .gather
   2595 					for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx)
   2596 					{
   2597 						const deUint32 filter = s_filters[filterNdx].filter;
   2598 
   2599 						if (!coreFilterable && filterRequiresFilterability(filter))
   2600 						{
   2601 							// skip linear on pure integers
   2602 							continue;
   2603 						}
   2604 						else if (s_filters[filterNdx].sampling == TextureBorderClampTest::SAMPLE_GATHER && targets[targetNdx].is3D)
   2605 						{
   2606 							// skip gather on 3d
   2607 							continue;
   2608 						}
   2609 						else
   2610 						{
   2611 							tcu::TestCaseGroup* const filteringGroup = new tcu::TestCaseGroup(m_testCtx, s_filters[filterNdx].name, "Tests with specific filter");
   2612 							formatGroup->addChild(filteringGroup);
   2613 
   2614 							// .s_XXX_t_XXX(_r_XXX)
   2615 							for (int wrapNdx = 0; wrapNdx < DE_LENGTH_OF_ARRAY(wrapConfigs); ++wrapNdx)
   2616 							{
   2617 								if (wrapConfigs[wrapNdx].is3D != targets[targetNdx].is3D)
   2618 									continue;
   2619 								else
   2620 								{
   2621 									for (int sizeNdx = 0; sizeNdx < 2; ++sizeNdx)
   2622 									{
   2623 										const char* const		wrapName			= wrapConfigs[wrapNdx].name;
   2624 										const bool				isNpotCase			= (sizeNdx == 1);
   2625 										const char* const		sizeNameExtension	= (isNpotCase) ? ("_npot") : ("_pot");
   2626 										const SizeType			size				= (isNpotCase) ? (SIZE_NPOT) : (SIZE_POT);
   2627 
   2628 										if (!targets[targetNdx].is3D)
   2629 											filteringGroup->addChild(new TextureBorderClampPerAxisCase2D(m_context,
   2630 																										 (std::string() + wrapName + sizeNameExtension).c_str(),
   2631 																										 "",
   2632 																										 format,
   2633 																										 sampleMode,
   2634 																										 size,
   2635 																										 filter,
   2636 																										 wrapConfigs[wrapNdx].sWrap,
   2637 																										 wrapConfigs[wrapNdx].tWrap,
   2638 																										 s_filters[filterNdx].sampling));
   2639 										else
   2640 										{
   2641 											DE_ASSERT(sampleMode == tcu::Sampler::MODE_LAST);
   2642 											filteringGroup->addChild(new TextureBorderClampPerAxisCase3D(m_context,
   2643 																										 (std::string() + wrapName + sizeNameExtension).c_str(),
   2644 																										 "",
   2645 																										 format,
   2646 																										 size,
   2647 																										 filter,
   2648 																										 wrapConfigs[wrapNdx].sWrap,
   2649 																										 wrapConfigs[wrapNdx].tWrap,
   2650 																										 wrapConfigs[wrapNdx].rWrap));
   2651 										}
   2652 									}
   2653 								}
   2654 							}
   2655 						}
   2656 					}
   2657 				}
   2658 			}
   2659 		}
   2660 	}
   2661 
   2662 	// .depth_compare_mode
   2663 	{
   2664 		static const struct
   2665 		{
   2666 			const char*						name;
   2667 			deUint32						format;
   2668 		} formats[] =
   2669 		{
   2670 			{ "depth_component16",		GL_DEPTH_COMPONENT16	},
   2671 			{ "depth_component24",		GL_DEPTH_COMPONENT24	},
   2672 			{ "depth24_stencil8",		GL_DEPTH24_STENCIL8		},
   2673 			{ "depth32f_stencil8",		GL_DEPTH32F_STENCIL8	},
   2674 		};
   2675 
   2676 		tcu::TestCaseGroup* const compareGroup = new tcu::TestCaseGroup(m_testCtx, "depth_compare_mode", "Tests depth compare mode");
   2677 		addChild(compareGroup);
   2678 
   2679 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
   2680 		{
   2681 			const deUint32							format			= formats[formatNdx].format;
   2682 			tcu::TestCaseGroup* const				formatGroup		= new tcu::TestCaseGroup(m_testCtx, formats[formatNdx].name, "Format test");
   2683 
   2684 			compareGroup->addChild(formatGroup);
   2685 
   2686 			// (format).(linear|nearest|gather)_(pot|npot)
   2687 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx)
   2688 			for (int sizeNdx = 0; sizeNdx < 2; ++sizeNdx)
   2689 			{
   2690 					const bool				isNpotCase		= (sizeNdx == 1);
   2691 					const char* const		sizeName		= (isNpotCase) ? ("size_npot") : ("size_pot");
   2692 					const SizeType			sizeType		= (isNpotCase) ? (SIZE_NPOT) : (SIZE_POT);
   2693 					const std::string		caseName		= std::string() + s_filters[filterNdx].name + "_" + sizeName;
   2694 					const deUint32			filter			= s_filters[filterNdx].filter;
   2695 
   2696 					formatGroup->addChild(new TextureBorderClampDepthCompareCase(m_context,
   2697 																				 caseName.c_str(),
   2698 																				 "",
   2699 																				 format,
   2700 																				 sizeType,
   2701 																				 filter,
   2702 																				 s_filters[filterNdx].sampling));
   2703 			}
   2704 		}
   2705 	}
   2706 
   2707 	// unused channels (A in rgb, G in stencil etc.)
   2708 	{
   2709 		static const struct
   2710 		{
   2711 			const char*						name;
   2712 			deUint32						format;
   2713 			tcu::Sampler::DepthStencilMode	mode;
   2714 		} formats[] =
   2715 		{
   2716 			{ "r8",										GL_R8,						tcu::Sampler::MODE_LAST		},
   2717 			{ "rg8_snorm",								GL_RG8_SNORM,				tcu::Sampler::MODE_LAST		},
   2718 			{ "rgb8",									GL_RGB8,					tcu::Sampler::MODE_LAST		},
   2719 			{ "rg32f",									GL_RG32F,					tcu::Sampler::MODE_LAST		},
   2720 			{ "r16i",									GL_RG16I,					tcu::Sampler::MODE_LAST		},
   2721 			{ "luminance",								GL_LUMINANCE,				tcu::Sampler::MODE_LAST		},
   2722 			{ "alpha",									GL_ALPHA,					tcu::Sampler::MODE_LAST		},
   2723 			{ "luminance_alpha",						GL_LUMINANCE_ALPHA,			tcu::Sampler::MODE_LAST		},
   2724 			{ "depth_component16",						GL_DEPTH_COMPONENT16,		tcu::Sampler::MODE_DEPTH	},
   2725 			{ "depth_component32f",						GL_DEPTH_COMPONENT32F,		tcu::Sampler::MODE_DEPTH	},
   2726 			{ "stencil_index8",							GL_STENCIL_INDEX8,			tcu::Sampler::MODE_STENCIL	},
   2727 			{ "depth32f_stencil8_sample_depth",			GL_DEPTH32F_STENCIL8,		tcu::Sampler::MODE_DEPTH	},
   2728 			{ "depth32f_stencil8_sample_stencil",		GL_DEPTH32F_STENCIL8,		tcu::Sampler::MODE_STENCIL	},
   2729 			{ "depth24_stencil8_sample_depth",			GL_DEPTH24_STENCIL8,		tcu::Sampler::MODE_DEPTH	},
   2730 			{ "depth24_stencil8_sample_stencil",		GL_DEPTH24_STENCIL8,		tcu::Sampler::MODE_STENCIL	},
   2731 			{ "compressed_r11_eac",						GL_COMPRESSED_R11_EAC,		tcu::Sampler::MODE_LAST		},
   2732 		};
   2733 
   2734 		tcu::TestCaseGroup* const unusedGroup = new tcu::TestCaseGroup(m_testCtx, "unused_channels", "Tests channels that are not present in the internal format");
   2735 		addChild(unusedGroup);
   2736 
   2737 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
   2738 		{
   2739 			unusedGroup->addChild(new TextureBorderClampUnusedChannelCase(m_context,
   2740 																		  formats[formatNdx].name,
   2741 																		  "",
   2742 																		  formats[formatNdx].format,
   2743 																		  formats[formatNdx].mode));
   2744 		}
   2745 	}
   2746 }
   2747 
   2748 } // Functional
   2749 } // gles31
   2750 } // deqp
   2751