• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
filterRequiresFilterability(deUint32 filter)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 
isDepthFormat(deUint32 format,tcu::Sampler::DepthStencilMode mode)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 
isStencilFormat(deUint32 format,tcu::Sampler::DepthStencilMode mode)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 
getFormatChannelClass(deUint32 format,tcu::Sampler::DepthStencilMode mode)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 
getDimensionNumBlocks(int dimensionSize,int blockSize)171 int getDimensionNumBlocks (int dimensionSize, int blockSize)
172 {
173 	// ceil( a / b )
174 	return (dimensionSize + blockSize - 1) / blockSize;
175 }
176 
generateDefaultCompressedData(tcu::CompressedTexture & dst,const tcu::CompressedTexFormat & format)177 void generateDefaultCompressedData (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 
createTextureFromInternalFormatdeqp::gles31::Functional::__anonec341bb20111::TextureTraits219 	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 
createTextureFromFormatAndTypedeqp::gles31::Functional::__anonec341bb20111::TextureTraits224 	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 
createTextureFromCompressedDatadeqp::gles31::Functional::__anonec341bb20111::TextureTraits229 	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 
getTextureNumLayersdeqp::gles31::Functional::__anonec341bb20111::TextureTraits241 	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 
createTextureFromInternalFormatdeqp::gles31::Functional::__anonec341bb20111::TextureTraits254 	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 
createTextureFromFormatAndTypedeqp::gles31::Functional::__anonec341bb20111::TextureTraits259 	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 
createTextureFromCompressedDatadeqp::gles31::Functional::__anonec341bb20111::TextureTraits264 	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 
getTextureNumLayersdeqp::gles31::Functional::__anonec341bb20111::TextureTraits276 	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>
genDefaultTexture(glu::RenderContext & renderCtx,const glu::ContextInfo & ctxInfo,deUint32 texFormat,const typename TextureTraits<T>::SizeType & size)284 de::MovePtr<T> genDefaultTexture (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 		generateDefaultCompressedData(compressedLevel, compressedFormat);
342 
343 		texture = TextureTraits<T>::createTextureFromCompressedData(renderCtx,
344 																	ctxInfo,
345 																	compressedLevel,
346 																	decompressionParams);
347 	}
348 
349 	return texture;
350 }
351 
getNBitIntegerMaxValue(bool isSigned,int numBits)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 
getNBitIntegerMinValue(bool isSigned,int numBits)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 
getNBitIntegerVec4MaxValue(bool isSigned,const tcu::IVec4 & numBits)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 
getNBitIntegerVec4MinValue(bool isSigned,const tcu::IVec4 & numBits)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 
mapToFormatColorUnits(const tcu::TextureFormat & texFormat,const tcu::Vec4 & normalizedRange)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 
mapToFormatColorRepresentable(const tcu::TextureFormat & texFormat,const tcu::Vec4 & normalizedRange)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 
isCoreFilterableFormat(deUint32 format,tcu::Sampler::DepthStencilMode mode)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 
TextureBorderClampTest(Context & context,const char * name,const char * description,deUint32 texFormat,tcu::Sampler::DepthStencilMode mode,StateType stateType,int texWidth,int texHeight,SamplingFunction samplingFunction,deUint32 flags)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 
~TextureBorderClampTest(void)644 TextureBorderClampTest::~TextureBorderClampTest (void)
645 {
646 	deinit();
647 }
648 
init(void)649 void TextureBorderClampTest::init (void)
650 {
651 	// requirements
652 	const bool supportsGL45			= glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5));
653 	const bool supportsES32orGL45	= glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) || supportsGL45;
654 
655 	if (!supportsES32orGL45 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_border_clamp"))
656 		throw tcu::NotSupportedError("Test requires GL_EXT_texture_border_clamp extension");
657 
658 	if (glu::isCompressedFormat(m_texFormat)													&&
659 		!supportsES32orGL45																		&&
660 		tcu::isAstcFormat(glu::mapGLCompressedTexFormat(m_texFormat))							&&
661 		!m_context.getContextInfo().isExtensionSupported("GL_KHR_texture_compression_astc_ldr"))
662 	{
663 		throw tcu::NotSupportedError("Test requires GL_KHR_texture_compression_astc_ldr extension");
664 	}
665 
666 	if (m_texFormat == GL_BGRA && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_format_BGRA8888"))
667 		throw tcu::NotSupportedError("Test requires GL_EXT_texture_format_BGRA8888 extension");
668 
669 	if (m_context.getRenderTarget().getWidth() < VIEWPORT_WIDTH ||
670 		m_context.getRenderTarget().getHeight() < VIEWPORT_HEIGHT)
671 	{
672 		throw tcu::NotSupportedError("Test requires " + de::toString<int>(VIEWPORT_WIDTH) + "x" + de::toString<int>(VIEWPORT_HEIGHT) + " viewport");
673 	}
674 
675 	// resources
676 
677 	m_texture = genDefaultTexture<glu::Texture2D>(m_context.getRenderContext(), m_context.getContextInfo(), m_texFormat, tcu::IVec2(m_texWidth, m_texHeight));
678 
679 	m_testCtx.getLog()	<< tcu::TestLog::Message
680 						<< "Created texture with format " << glu::getTextureFormatName(m_texFormat)
681 						<< ", size (" << m_texture->getRefTexture().getWidth() << ", " << m_texture->getRefTexture().getHeight() << ")\n"
682 						<< "Setting sampling state using " << ((m_stateType == STATE_TEXTURE_PARAM) ? ("texture state") : ("sampler state"))
683 						<< tcu::TestLog::EndMessage;
684 
685 	if (m_samplingFunction == SAMPLE_FILTER)
686 	{
687 		const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType());
688 
689 		m_renderer = de::MovePtr<gls::TextureTestUtil::TextureRenderer>(new gls::TextureTestUtil::TextureRenderer(m_context.getRenderContext(), m_testCtx.getLog(), glslVersion, glu::PRECISION_HIGHP));
690 	}
691 	else
692 	{
693 		m_gatherProgram = de::MovePtr<glu::ShaderProgram>(genGatherProgram());
694 
695 		m_testCtx.getLog()	<< tcu::TestLog::Message
696 							<< "Using texture gather to sample texture"
697 							<< tcu::TestLog::EndMessage
698 							<< *m_gatherProgram;
699 
700 		if (!m_gatherProgram->isOk())
701 			throw tcu::TestError("failed to build program");
702 	}
703 }
704 
deinit(void)705 void TextureBorderClampTest::deinit (void)
706 {
707 	m_texture.clear();
708 	m_renderer.clear();
709 	m_gatherProgram.clear();
710 }
711 
iterate(void)712 TextureBorderClampTest::IterateResult TextureBorderClampTest::iterate (void)
713 {
714 	const IterationConfig						iterationConfig		= getIteration(m_iterationNdx);
715 	const std::string							iterationDesc		= "Iteration " + de::toString(m_iterationNdx+1) + (iterationConfig.description.empty() ? ("") : (" - " + iterationConfig.description));
716 	const tcu::ScopedLogSection					section				(m_testCtx.getLog(), "Iteration", iterationDesc);
717 	tcu::Surface								renderedFrame		(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
718 	const glu::TextureTestUtil::ReferenceParams	samplerParams		= genSamplerParams(iterationConfig);
719 
720 	logParams(iterationConfig, samplerParams);
721 	renderTo(renderedFrame, iterationConfig, samplerParams);
722 	verifyImage(renderedFrame, iterationConfig, samplerParams);
723 
724 	if (++m_iterationNdx == getNumIterations())
725 	{
726 		m_result.setTestContextResult(m_testCtx);
727 		return STOP;
728 	}
729 	return CONTINUE;
730 }
731 
logParams(const IterationConfig & config,const glu::TextureTestUtil::ReferenceParams & samplerParams)732 void TextureBorderClampTest::logParams (const IterationConfig& config, const glu::TextureTestUtil::ReferenceParams& samplerParams)
733 {
734 	const std::string				borderColorString	= (m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)   ? (de::toString(config.borderColor.get<deInt32>()))
735 														: (m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) ? (de::toString(config.borderColor.get<deUint32>()))
736 														:																  (de::toString(config.borderColor.get<float>()));
737 
738 	m_testCtx.getLog()	<< tcu::TestLog::Message
739 						<< "Rendering full screen quad, tex coords bottom-left: " << config.p0 << ", top-right " << config.p1 << "\n"
740 						<< "Border color is " << borderColorString << "\n"
741 						<< "Texture lookup bias: " << samplerParams.colorBias << "\n"
742 						<< "Texture lookup scale: " << samplerParams.colorScale << "\n"
743 						<< "Filters: min = " << glu::getTextureFilterName(glu::getGLFilterMode(samplerParams.sampler.minFilter))
744 							<< ", mag = " << glu::getTextureFilterName(glu::getGLFilterMode(samplerParams.sampler.magFilter)) << "\n"
745 						<< "Wrap mode: s = " << glu::getRepeatModeStr(config.sWrapMode)
746 							<< ", t = " << glu::getRepeatModeStr(config.tWrapMode) << "\n"
747 						<< tcu::TestLog::EndMessage;
748 
749 	if (m_sampleMode == tcu::Sampler::MODE_DEPTH)
750 		m_testCtx.getLog() << tcu::TestLog::Message << "Depth stencil texture mode is DEPTH_COMPONENT" << tcu::TestLog::EndMessage;
751 	else if (m_sampleMode == tcu::Sampler::MODE_STENCIL)
752 		m_testCtx.getLog() << tcu::TestLog::Message << "Depth stencil texture mode is STENCIL_INDEX" << tcu::TestLog::EndMessage;
753 
754 	if (config.compareMode != GL_NONE)
755 	{
756 		m_testCtx.getLog()	<< tcu::TestLog::Message
757 							<< "Texture mode is COMPARE_REF_TO_TEXTURE, mode = " << glu::getCompareFuncStr(config.compareMode) << "\n"
758 							<< "Compare reference value = " << config.compareRef << "\n"
759 							<< tcu::TestLog::EndMessage;
760 	}
761 }
762 
renderTo(tcu::Surface & surface,const IterationConfig & config,const glu::TextureTestUtil::ReferenceParams & samplerParams)763 void TextureBorderClampTest::renderTo (tcu::Surface&								surface,
764 									   const IterationConfig&						config,
765 									   const glu::TextureTestUtil::ReferenceParams&	samplerParams)
766 {
767 	const glw::Functions&						gl			= m_context.getRenderContext().getFunctions();
768 	const gls::TextureTestUtil::RandomViewport	viewport	(m_context.getRenderTarget(), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, getIterationSeed(config));
769 	std::vector<float>							texCoord;
770 	de::MovePtr<glu::Sampler>					sampler;
771 
772 	glu::TextureTestUtil::computeQuadTexCoord2D(texCoord, config.p0, config.p1);
773 
774 	// Bind to unit 0.
775 	gl.activeTexture(GL_TEXTURE0);
776 	gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());
777 
778 	if (m_sampleMode == tcu::Sampler::MODE_DEPTH)
779 		gl.texParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT);
780 	else if (m_sampleMode == tcu::Sampler::MODE_STENCIL)
781 		gl.texParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
782 
783 	if (config.compareMode == GL_NONE)
784 	{
785 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
786 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_ALWAYS);
787 	}
788 	else
789 	{
790 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
791 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, config.compareMode);
792 	}
793 
794 	if (m_stateType == STATE_TEXTURE_PARAM)
795 	{
796 		// Setup filtering and wrap modes.
797 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		glu::getGLWrapMode(samplerParams.sampler.wrapS));
798 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		glu::getGLWrapMode(samplerParams.sampler.wrapT));
799 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	glu::getGLFilterMode(samplerParams.sampler.minFilter));
800 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	glu::getGLFilterMode(samplerParams.sampler.magFilter));
801 
802 		switch (m_channelClass)
803 		{
804 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
805 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
806 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
807 				gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<float>());
808 				break;
809 
810 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
811 				gl.texParameterIiv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<deInt32>());
812 				break;
813 
814 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
815 				gl.texParameterIuiv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<deUint32>());
816 				break;
817 
818 			default:
819 				DE_ASSERT(false);
820 		}
821 	}
822 	else if (m_stateType == STATE_SAMPLER_PARAM)
823 	{
824 		const tcu::Vec4 blue(0.0f, 0.0f, 1.0f, 1.0f);
825 
826 		// Setup filtering and wrap modes to bad values
827 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		GL_REPEAT);
828 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		GL_REPEAT);
829 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
830 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
831 		gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, blue.getPtr()); // just set some unlikely color
832 
833 		// setup sampler to correct values
834 		sampler = de::MovePtr<glu::Sampler>(new glu::Sampler(m_context.getRenderContext()));
835 
836 		gl.samplerParameteri(**sampler, GL_TEXTURE_WRAP_S,		glu::getGLWrapMode(samplerParams.sampler.wrapS));
837 		gl.samplerParameteri(**sampler, GL_TEXTURE_WRAP_T,		glu::getGLWrapMode(samplerParams.sampler.wrapT));
838 		gl.samplerParameteri(**sampler, GL_TEXTURE_MIN_FILTER,	glu::getGLFilterMode(samplerParams.sampler.minFilter));
839 		gl.samplerParameteri(**sampler, GL_TEXTURE_MAG_FILTER,	glu::getGLFilterMode(samplerParams.sampler.magFilter));
840 
841 		switch (m_channelClass)
842 		{
843 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
844 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
845 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
846 				gl.samplerParameterfv(**sampler, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<float>());
847 				break;
848 
849 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
850 				gl.samplerParameterIiv(**sampler, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<deInt32>());
851 				break;
852 
853 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
854 				gl.samplerParameterIuiv(**sampler, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<deUint32>());
855 				break;
856 
857 			default:
858 				DE_ASSERT(false);
859 		}
860 
861 		gl.bindSampler(0, **sampler);
862 	}
863 
864 	GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
865 
866 	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
867 	renderQuad(&texCoord[0], samplerParams);
868 	glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, surface.getAccess());
869 }
870 
renderQuad(const float * texCoord,const glu::TextureTestUtil::ReferenceParams & samplerParams)871 void TextureBorderClampTest::renderQuad (const float* texCoord, const glu::TextureTestUtil::ReferenceParams& samplerParams)
872 {
873 	// use TextureRenderer for basic rendering, use custom for gather
874 	if (m_samplingFunction == SAMPLE_FILTER)
875 		m_renderer->renderQuad(0, texCoord, samplerParams);
876 	else
877 	{
878 		static const float position[] =
879 		{
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 			+1.0f, +1.0f, 0.0f, 1.0f
884 		};
885 		static const deUint16 indices[] =
886 		{
887 			0, 1, 2, 2, 1, 3
888 		};
889 		const glu::VertexArrayBinding vertexArrays[] =
890 		{
891 			glu::va::Float("a_position",	4,	4, 0, &position[0]),
892 			glu::va::Float("a_texcoord",	2,	4, 0, texCoord)
893 		};
894 
895 		const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
896 		const deUint32			progId	= m_gatherProgram->getProgram();
897 
898 		gl.useProgram(progId);
899 		gl.uniform1i(gl.getUniformLocation(progId, "u_sampler"), 0);
900 		if (m_useShadowSampler)
901 			gl.uniform1f(gl.getUniformLocation(progId, "u_ref"), samplerParams.ref);
902 		gl.uniform4fv(gl.getUniformLocation(progId, "u_colorScale"), 1, samplerParams.colorScale.getPtr());
903 		gl.uniform4fv(gl.getUniformLocation(progId, "u_colorBias"), 1, samplerParams.colorBias.getPtr());
904 
905 		glu::draw(m_context.getRenderContext(), progId, DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0],
906 					glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
907 	}
908 }
909 
verifyImage(const tcu::Surface & renderedFrame,const IterationConfig & config,const glu::TextureTestUtil::ReferenceParams & samplerParams)910 void TextureBorderClampTest::verifyImage (const tcu::Surface&							renderedFrame,
911 										  const IterationConfig&						config,
912 										  const glu::TextureTestUtil::ReferenceParams&	samplerParams)
913 {
914 	const tcu::PixelFormat	pixelFormat		= m_context.getRenderTarget().getPixelFormat();
915 
916 	tcu::LodPrecision		lodPrecision;
917 	std::vector<float>		texCoord;
918 	bool					verificationOk;
919 
920 	glu::TextureTestUtil::computeQuadTexCoord2D(texCoord, config.p0, config.p1);
921 
922 	lodPrecision.derivateBits		= 18;
923 	lodPrecision.lodBits			= 5;
924 
925 	if (samplerParams.sampler.compare == tcu::Sampler::COMPAREMODE_NONE)
926 	{
927 		const tcu::TextureFormat		texFormat			= tcu::getEffectiveDepthStencilTextureFormat(m_texture->getRefTexture().getFormat(), m_sampleMode);
928 		const bool						isNearestMinFilter	= samplerParams.sampler.minFilter == tcu::Sampler::NEAREST || samplerParams.sampler.minFilter == tcu::Sampler::NEAREST_MIPMAP_NEAREST;
929 		const bool						isNearestMagFilter	= samplerParams.sampler.magFilter == tcu::Sampler::NEAREST;
930 		const bool						isNearestOnly		= isNearestMinFilter && isNearestMagFilter;
931 		const bool						isSRGB				= texFormat.order == tcu::TextureFormat::sRGB || texFormat.order == tcu::TextureFormat::sRGBA;
932 		const int						colorErrorBits		= (isNearestOnly && !isSRGB) ? (1) : (2);
933 		const tcu::IVec4				colorBits			= tcu::max(glu::TextureTestUtil::getBitsVec(pixelFormat) - tcu::IVec4(colorErrorBits), tcu::IVec4(0));
934 		tcu::LookupPrecision			lookupPrecision;
935 
936 		lookupPrecision.colorThreshold	= tcu::computeFixedPointThreshold(colorBits) / samplerParams.colorScale;
937 		lookupPrecision.coordBits		= tcu::IVec3(20,20,0);
938 		lookupPrecision.uvwBits			= tcu::IVec3(5,5,0);
939 		lookupPrecision.colorMask		= glu::TextureTestUtil::getCompareMask(pixelFormat);
940 
941 		if (m_samplingFunction == SAMPLE_FILTER)
942 		{
943 			verificationOk = verifyTextureSampleResult(renderedFrame.getAccess(),
944 													   &texCoord[0],
945 													   samplerParams,
946 													   lodPrecision,
947 													   lookupPrecision);
948 		}
949 		else if (m_samplingFunction == SAMPLE_GATHER)
950 		{
951 			verificationOk = verifyTextureGatherResult(renderedFrame.getAccess(),
952 													   &texCoord[0],
953 													   samplerParams,
954 													   lookupPrecision);
955 		}
956 		else
957 		{
958 			DE_ASSERT(false);
959 			verificationOk = false;
960 		}
961 	}
962 	else
963 	{
964 		tcu::TexComparePrecision	texComparePrecision;
965 		tcu::TexComparePrecision	lowQualityTexComparePrecision;
966 		tcu::LodPrecision			lowQualityLodPrecision			= lodPrecision;
967 
968 		texComparePrecision.coordBits					= tcu::IVec3(20,20,0);
969 		texComparePrecision.uvwBits						= tcu::IVec3(7,7,0);
970 		texComparePrecision.pcfBits						= 5;
971 		texComparePrecision.referenceBits				= 16;
972 		texComparePrecision.resultBits					= de::max(0, pixelFormat.redBits - 1);
973 
974 		lowQualityTexComparePrecision.coordBits			= tcu::IVec3(20,20,0);
975 		lowQualityTexComparePrecision.uvwBits			= tcu::IVec3(4,4,0);
976 		lowQualityTexComparePrecision.pcfBits			= 0;
977 		lowQualityTexComparePrecision.referenceBits		= 16;
978 		lowQualityTexComparePrecision.resultBits		= de::max(0, pixelFormat.redBits - 1);
979 
980 		lowQualityLodPrecision.lodBits					= 4;
981 
982 		if (m_samplingFunction == SAMPLE_FILTER)
983 		{
984 			verificationOk = verifyTextureCompareResult(renderedFrame.getAccess(),
985 														&texCoord[0],
986 														samplerParams,
987 														texComparePrecision,
988 														lowQualityTexComparePrecision,
989 														lodPrecision,
990 														lowQualityLodPrecision);
991 		}
992 		else if (m_samplingFunction == SAMPLE_GATHER)
993 		{
994 			verificationOk = verifyTextureGatherCmpResult(renderedFrame.getAccess(),
995 														  &texCoord[0],
996 														  samplerParams,
997 														  texComparePrecision,
998 														  lowQualityTexComparePrecision);
999 		}
1000 		else
1001 		{
1002 			DE_ASSERT(false);
1003 			verificationOk = false;
1004 		}
1005 	}
1006 
1007 	if (!verificationOk)
1008 		m_result.fail("Image verification failed");
1009 }
1010 
verifyTextureSampleResult(const tcu::ConstPixelBufferAccess & renderedFrame,const float * texCoord,const glu::TextureTestUtil::ReferenceParams & samplerParams,const tcu::LodPrecision & lodPrecision,const tcu::LookupPrecision & lookupPrecision)1011 bool TextureBorderClampTest::verifyTextureSampleResult (const tcu::ConstPixelBufferAccess&				renderedFrame,
1012 														const float*									texCoord,
1013 														const glu::TextureTestUtil::ReferenceParams&	samplerParams,
1014 														const tcu::LodPrecision&						lodPrecision,
1015 													    const tcu::LookupPrecision&						lookupPrecision)
1016 {
1017 	const tcu::PixelFormat			pixelFormat			= m_context.getRenderTarget().getPixelFormat();
1018 	tcu::Surface					reference			(renderedFrame.getWidth(), renderedFrame.getHeight());
1019 	tcu::Surface					errorMask			(renderedFrame.getWidth(), renderedFrame.getHeight());
1020 	int								numFailedPixels;
1021 
1022 	glu::TextureTestUtil::sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), m_texture->getRefTexture(), texCoord, samplerParams);
1023 
1024 	numFailedPixels = glu::TextureTestUtil::computeTextureLookupDiff(renderedFrame, reference.getAccess(), errorMask.getAccess(), m_texture->getRefTexture(),
1025 																	 texCoord, samplerParams, lookupPrecision, lodPrecision, m_testCtx.getWatchDog());
1026 
1027 	if (numFailedPixels > 0)
1028 		m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
1029 	m_testCtx.getLog()	<< tcu::TestLog::ImageSet("VerifyResult", "Verification result")
1030 						<< tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame);
1031 	if (numFailedPixels > 0)
1032 	{
1033 		m_testCtx.getLog()	<< tcu::TestLog::Image("Reference", "Ideal reference image", reference)
1034 							<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
1035 	}
1036 	m_testCtx.getLog() << tcu::TestLog::EndImageSet;
1037 
1038 	return (numFailedPixels == 0);
1039 }
1040 
verifyTextureCompareResult(const tcu::ConstPixelBufferAccess & renderedFrame,const float * texCoord,const glu::TextureTestUtil::ReferenceParams & samplerParams,const tcu::TexComparePrecision & texComparePrecision,const tcu::TexComparePrecision & lowQualityTexComparePrecision,const tcu::LodPrecision & lodPrecision,const tcu::LodPrecision & lowQualityLodPrecision)1041 bool TextureBorderClampTest::verifyTextureCompareResult (const tcu::ConstPixelBufferAccess&				renderedFrame,
1042 														 const float*									texCoord,
1043 														 const glu::TextureTestUtil::ReferenceParams&	samplerParams,
1044 													     const tcu::TexComparePrecision&				texComparePrecision,
1045 													     const tcu::TexComparePrecision&				lowQualityTexComparePrecision,
1046 														 const tcu::LodPrecision&						lodPrecision,
1047 														 const tcu::LodPrecision&						lowQualityLodPrecision)
1048 {
1049 	const tcu::PixelFormat						pixelFormat				= m_context.getRenderTarget().getPixelFormat();
1050 	const int									colorErrorBits			= 1;
1051 	const tcu::IVec4							nonShadowBits			= tcu::max(glu::TextureTestUtil::getBitsVec(pixelFormat) - tcu::IVec4(colorErrorBits), tcu::IVec4(0));
1052 	const tcu::Vec3								nonShadowThreshold		= tcu::computeFixedPointThreshold(nonShadowBits).swizzle(1,2,3);
1053 	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
1054 	const tcu::Texture2DView					effectiveView			= tcu::getEffectiveTextureView(m_texture->getRefTexture(), srcLevelStorage, samplerParams.sampler);
1055 	tcu::Surface								reference				(renderedFrame.getWidth(), renderedFrame.getHeight());
1056 	tcu::Surface								errorMask				(renderedFrame.getWidth(), renderedFrame.getHeight());
1057 	int											numFailedPixels;
1058 
1059 	glu::TextureTestUtil::sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), effectiveView, texCoord, samplerParams);
1060 
1061 	numFailedPixels = glu::TextureTestUtil::computeTextureCompareDiff(renderedFrame, reference.getAccess(), errorMask.getAccess(), effectiveView,
1062 																	  texCoord, samplerParams, texComparePrecision, lodPrecision, nonShadowThreshold);
1063 
1064 	if (numFailedPixels > 0)
1065 	{
1066 		m_testCtx.getLog()	<< tcu::TestLog::Message
1067 							<< "Warning: Verification assuming high-quality PCF filtering failed."
1068 							<< tcu::TestLog::EndMessage;
1069 
1070 		numFailedPixels = glu::TextureTestUtil::computeTextureCompareDiff(renderedFrame, reference.getAccess(), errorMask.getAccess(), effectiveView,
1071 																		  texCoord, samplerParams, lowQualityTexComparePrecision, lowQualityLodPrecision, nonShadowThreshold);
1072 
1073 		if (numFailedPixels > 0)
1074 			m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << tcu::TestLog::EndMessage;
1075 		else if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1076 			m_result.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality result");
1077 	}
1078 
1079 	if (numFailedPixels > 0)
1080 		m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
1081 	m_testCtx.getLog()	<< tcu::TestLog::ImageSet("VerifyResult", "Verification result")
1082 						<< tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame);
1083 	if (numFailedPixels > 0)
1084 	{
1085 		m_testCtx.getLog()	<< tcu::TestLog::Image("Reference", "Ideal reference image", reference)
1086 							<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
1087 	}
1088 	m_testCtx.getLog() << tcu::TestLog::EndImageSet;
1089 
1090 	return (numFailedPixels == 0);
1091 }
1092 
1093 template <typename T>
triQuadInterpolate(const T (& values)[4],float xFactor,float yFactor)1094 static inline T triQuadInterpolate (const T (&values)[4], float xFactor, float yFactor)
1095 {
1096 	if (xFactor + yFactor < 1.0f)
1097 		return values[0] + (values[2]-values[0])*xFactor		+ (values[1]-values[0])*yFactor;
1098 	else
1099 		return values[3] + (values[1]-values[3])*(1.0f-xFactor)	+ (values[2]-values[3])*(1.0f-yFactor);
1100 }
1101 
verifyTextureGatherResult(const tcu::ConstPixelBufferAccess & renderedFrame,const float * texCoordArray,const glu::TextureTestUtil::ReferenceParams & samplerParams,const tcu::LookupPrecision & lookupPrecision)1102 bool TextureBorderClampTest::verifyTextureGatherResult (const tcu::ConstPixelBufferAccess&				renderedFrame,
1103 														const float*									texCoordArray,
1104 														const glu::TextureTestUtil::ReferenceParams&	samplerParams,
1105 														const tcu::LookupPrecision&						lookupPrecision)
1106 {
1107 	const tcu::Vec2 texCoords[4] =
1108 	{
1109 		tcu::Vec2(texCoordArray[0], texCoordArray[1]),
1110 		tcu::Vec2(texCoordArray[2], texCoordArray[3]),
1111 		tcu::Vec2(texCoordArray[4], texCoordArray[5]),
1112 		tcu::Vec2(texCoordArray[6], texCoordArray[7]),
1113 	};
1114 
1115 	const tcu::PixelFormat						pixelFormat			= m_context.getRenderTarget().getPixelFormat();
1116 	const deUint8								fbColormask			= tcu::getColorMask(pixelFormat);
1117 
1118 	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
1119 	const tcu::Texture2DView					effectiveView		= tcu::getEffectiveTextureView(m_texture->getRefTexture(), srcLevelStorage, samplerParams.sampler);
1120 
1121 	tcu::Surface								reference			(renderedFrame.getWidth(), renderedFrame.getHeight());
1122 	tcu::Surface								errorMask			(renderedFrame.getWidth(), renderedFrame.getHeight());
1123 	int											numFailedPixels		= 0;
1124 
1125 	tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec());
1126 
1127 	for (int py = 0; py < reference.getHeight(); ++py)
1128 	for (int px = 0; px < reference.getWidth(); ++px)
1129 	{
1130 		const tcu::Vec2			viewportCoord	= (tcu::Vec2((float)px, (float)py) + tcu::Vec2(0.5f)) / tcu::Vec2((float)reference.getWidth(), (float)reference.getHeight());
1131 		const tcu::Vec2			texCoord		= triQuadInterpolate(texCoords, viewportCoord.x(), viewportCoord.y());
1132 		const tcu::Vec4			referenceValue	= effectiveView.gatherOffsets(samplerParams.sampler, texCoord.x(), texCoord.y(), 0, glu::getDefaultGatherOffsets());
1133 		const tcu::Vec4			referencePixel	= referenceValue * samplerParams.colorScale + samplerParams.colorBias;
1134 		const tcu::Vec4			resultPixel		= renderedFrame.getPixel(px, py);
1135 		const tcu::Vec4			resultValue		= (resultPixel - samplerParams.colorBias) / samplerParams.colorScale;
1136 
1137 		reference.setPixel(px, py, tcu::toRGBAMasked(referenceValue, fbColormask));
1138 
1139 		if (tcu::boolAny(tcu::logicalAnd(lookupPrecision.colorMask,
1140 										 tcu::greaterThan(tcu::absDiff(resultPixel, referencePixel),
1141 														  lookupPrecision.colorThreshold))))
1142 		{
1143 			if (!tcu::isGatherOffsetsResultValid(effectiveView, samplerParams.sampler, lookupPrecision, texCoord, 0, glu::getDefaultGatherOffsets(), resultValue))
1144 			{
1145 				errorMask.setPixel(px, py, tcu::RGBA::red());
1146 				++numFailedPixels;
1147 			}
1148 		}
1149 	}
1150 
1151 	if (numFailedPixels > 0)
1152 		m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
1153 	m_testCtx.getLog()	<< tcu::TestLog::ImageSet("VerifyResult", "Verification result")
1154 						<< tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame);
1155 	if (numFailedPixels > 0)
1156 	{
1157 		m_testCtx.getLog()	<< tcu::TestLog::Image("Reference", "Ideal reference image", reference)
1158 							<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
1159 	}
1160 	m_testCtx.getLog() << tcu::TestLog::EndImageSet;
1161 
1162 	return (numFailedPixels == 0);
1163 }
1164 
verifyTextureGatherCmpResult(const tcu::ConstPixelBufferAccess & renderedFrame,const float * texCoordArray,const glu::TextureTestUtil::ReferenceParams & samplerParams,const tcu::TexComparePrecision & texComparePrecision,const tcu::TexComparePrecision & lowQualityTexComparePrecision)1165 bool TextureBorderClampTest::verifyTextureGatherCmpResult (const tcu::ConstPixelBufferAccess&			renderedFrame,
1166 														   const float*									texCoordArray,
1167 														   const glu::TextureTestUtil::ReferenceParams&	samplerParams,
1168 														   const tcu::TexComparePrecision&				texComparePrecision,
1169 														   const tcu::TexComparePrecision&				lowQualityTexComparePrecision)
1170 {
1171 	const tcu::Vec2 texCoords[4] =
1172 	{
1173 		tcu::Vec2(texCoordArray[0], texCoordArray[1]),
1174 		tcu::Vec2(texCoordArray[2], texCoordArray[3]),
1175 		tcu::Vec2(texCoordArray[4], texCoordArray[5]),
1176 		tcu::Vec2(texCoordArray[6], texCoordArray[7]),
1177 	};
1178 
1179 	std::vector<tcu::ConstPixelBufferAccess>	srcLevelStorage;
1180 	const tcu::Texture2DView					effectiveView		= tcu::getEffectiveTextureView(m_texture->getRefTexture(), srcLevelStorage, samplerParams.sampler);
1181 
1182 	const tcu::PixelFormat						pixelFormat			= m_context.getRenderTarget().getPixelFormat();
1183 	const tcu::BVec4							colorMask			= glu::TextureTestUtil::getCompareMask(pixelFormat);
1184 	const deUint8								fbColormask			= tcu::getColorMask(pixelFormat);
1185 	tcu::Surface								reference			(renderedFrame.getWidth(), renderedFrame.getHeight());
1186 	tcu::Surface								errorMask			(renderedFrame.getWidth(), renderedFrame.getHeight());
1187 	int											numFailedPixels		= 0;
1188 	bool										lowQuality			= false;
1189 
1190 	tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec());
1191 
1192 	for (int py = 0; py < reference.getHeight(); ++py)
1193 	for (int px = 0; px < reference.getWidth(); ++px)
1194 	{
1195 		const tcu::Vec2			viewportCoord	= (tcu::Vec2((float)px, (float)py) + tcu::Vec2(0.5f)) / tcu::Vec2((float)reference.getWidth(), (float)reference.getHeight());
1196 		const tcu::Vec2			texCoord		= triQuadInterpolate(texCoords, viewportCoord.x(), viewportCoord.y());
1197 		const float				refZ			= samplerParams.ref;
1198 		const tcu::Vec4			referenceValue	= effectiveView.gatherOffsetsCompare(samplerParams.sampler, refZ, texCoord.x(), texCoord.y(), glu::getDefaultGatherOffsets());
1199 		const tcu::Vec4			resultValue		= renderedFrame.getPixel(px, py);
1200 
1201 		reference.setPixel(px, py, tcu::toRGBAMasked(referenceValue, fbColormask));
1202 
1203 		if (tcu::boolAny(tcu::logicalAnd(colorMask, tcu::notEqual(referenceValue, resultValue))))
1204 		{
1205 			if (!tcu::isGatherOffsetsCompareResultValid(effectiveView, samplerParams.sampler, texComparePrecision, texCoord, glu::getDefaultGatherOffsets(), refZ, resultValue))
1206 			{
1207 				lowQuality = true;
1208 
1209 				// fall back to low quality verification
1210 				if (!tcu::isGatherOffsetsCompareResultValid(effectiveView, samplerParams.sampler, lowQualityTexComparePrecision, texCoord, glu::getDefaultGatherOffsets(), refZ, resultValue))
1211 				{
1212 					errorMask.setPixel(px, py, tcu::RGBA::red());
1213 					++numFailedPixels;
1214 				}
1215 			}
1216 		}
1217 	}
1218 
1219 	if (numFailedPixels > 0)
1220 		m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
1221 	else if (lowQuality)
1222 	{
1223 		m_testCtx.getLog() << tcu::TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << tcu::TestLog::EndMessage;
1224 		m_result.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality result");
1225 	}
1226 
1227 	m_testCtx.getLog()	<< tcu::TestLog::ImageSet("VerifyResult", "Verification result")
1228 						<< tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame);
1229 	if (numFailedPixels > 0)
1230 	{
1231 		m_testCtx.getLog()	<< tcu::TestLog::Image("Reference", "Ideal reference image", reference)
1232 							<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
1233 	}
1234 	m_testCtx.getLog() << tcu::TestLog::EndImageSet;
1235 
1236 	return (numFailedPixels == 0);
1237 }
1238 
getTexture(void) const1239 const glu::Texture2D* TextureBorderClampTest::getTexture (void) const
1240 {
1241 	return m_texture.get();
1242 }
1243 
getIterationSeed(const IterationConfig & config) const1244 deUint32 TextureBorderClampTest::getIterationSeed (const IterationConfig& config) const
1245 {
1246 	tcu::SeedBuilder builder;
1247 	builder	<< std::string(getName())
1248 			<< m_iterationNdx
1249 			<< m_texFormat
1250 			<< config.minFilter << config.magFilter
1251 			<< m_texture->getRefTexture().getWidth() << m_texture->getRefTexture().getHeight();
1252 	return builder.get();
1253 }
1254 
genSamplerParams(const IterationConfig & config) const1255 glu::TextureTestUtil::ReferenceParams TextureBorderClampTest::genSamplerParams (const IterationConfig& config) const
1256 {
1257 	const tcu::TextureFormat				texFormat		= tcu::getEffectiveDepthStencilTextureFormat(m_texture->getRefTexture().getFormat(), m_sampleMode);
1258 	glu::TextureTestUtil::ReferenceParams	refParams		(glu::TextureTestUtil::TEXTURETYPE_2D);
1259 
1260 	refParams.sampler					= glu::mapGLSampler(config.sWrapMode, config.tWrapMode, config.minFilter, config.magFilter);
1261 	refParams.sampler.borderColor		= config.borderColor;
1262 	refParams.sampler.compare			= (!m_useShadowSampler) ? (tcu::Sampler::COMPAREMODE_NONE) : (glu::mapGLCompareFunc(config.compareMode));
1263 	refParams.sampler.depthStencilMode	= m_sampleMode;
1264 	refParams.lodMode					= glu::TextureTestUtil::LODMODE_EXACT;
1265 	refParams.samplerType				= (!m_useShadowSampler) ? (glu::TextureTestUtil::getSamplerType(texFormat)) : (glu::TextureTestUtil::SAMPLERTYPE_SHADOW);
1266 	refParams.colorScale				= config.lookupScale;
1267 	refParams.colorBias					= config.lookupBias;
1268 	refParams.ref						= config.compareRef;
1269 
1270 	// compare can only be used with depth textures
1271 	if (!isDepthFormat(m_texFormat, m_sampleMode))
1272 		DE_ASSERT(refParams.sampler.compare == tcu::Sampler::COMPAREMODE_NONE);
1273 
1274 	// sampler type must match compare mode
1275 	DE_ASSERT(m_useShadowSampler == (config.compareMode != GL_NONE));
1276 
1277 	// in gather, weird mapping is most likely an error
1278 	if (m_samplingFunction == SAMPLE_GATHER)
1279 	{
1280 		DE_ASSERT(refParams.colorScale == tcu::Vec4(refParams.colorScale.x()));
1281 		DE_ASSERT(refParams.colorBias == tcu::Vec4(refParams.colorBias.x()));
1282 	}
1283 
1284 	return refParams;
1285 }
1286 
genGatherProgram(void) const1287 glu::ShaderProgram* TextureBorderClampTest::genGatherProgram (void) const
1288 {
1289 	const std::string	glslVersionDecl	= glu::getGLSLVersionDeclaration(glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType()));
1290 	const std::string	vtxSource		= glslVersionDecl + "\n"
1291 										"in highp vec4 a_position;\n"
1292 										"in highp vec2 a_texcoord;\n"
1293 										"out highp vec2 v_texcoord;\n"
1294 										"void main()\n"
1295 										"{\n"
1296 										"	gl_Position = a_position;\n"
1297 										"	v_texcoord = a_texcoord;\n"
1298 										"}\n";
1299 	const char*			samplerType;
1300 	const char*			lookup;
1301 	std::ostringstream	fragSource;
1302 
1303 	if (m_useShadowSampler)
1304 	{
1305 		samplerType	= "sampler2DShadow";
1306 		lookup		= "textureGather(u_sampler, v_texcoord, u_ref)";
1307 	}
1308 	else
1309 	{
1310 		switch (m_channelClass)
1311 		{
1312 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1313 			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1314 			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1315 				samplerType	= "sampler2D";
1316 				lookup		= "textureGather(u_sampler, v_texcoord)";
1317 				break;
1318 
1319 			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1320 				samplerType	= "isampler2D";
1321 				lookup		= "vec4(textureGather(u_sampler, v_texcoord))";
1322 				break;
1323 
1324 			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1325 				samplerType	= "usampler2D";
1326 				lookup		= "vec4(textureGather(u_sampler, v_texcoord))";
1327 				break;
1328 
1329 			default:
1330 				samplerType	= "";
1331 				lookup		= "";
1332 				DE_ASSERT(false);
1333 		}
1334 	}
1335 
1336 	fragSource	<<	glslVersionDecl + "\n"
1337 					"uniform highp " << samplerType << " u_sampler;\n"
1338 					"uniform highp vec4 u_colorScale;\n"
1339 					"uniform highp vec4 u_colorBias;\n"
1340 				<<	((m_useShadowSampler) ? ("uniform highp float u_ref;\n") : (""))
1341 				<<	"in highp vec2 v_texcoord;\n"
1342 					"layout(location=0) out highp vec4 o_color;\n"
1343 					"void main()\n"
1344 					"{\n"
1345 					"	o_color = " << lookup << " * u_colorScale + u_colorBias;\n"
1346 					"}\n";
1347 
1348 	return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(vtxSource) << glu::FragmentSource(fragSource.str()));
1349 }
1350 
1351 class TextureBorderClampFormatCase : public TextureBorderClampTest
1352 {
1353 public:
1354 									TextureBorderClampFormatCase	(Context&						context,
1355 																	 const char*					name,
1356 																	 const char*					description,
1357 																	 deUint32						texFormat,
1358 																	 tcu::Sampler::DepthStencilMode	mode,
1359 																	 StateType						stateType,
1360 																	 SizeType						sizeType,
1361 																	 deUint32						filter,
1362 																	 SamplingFunction				samplingFunction);
1363 
1364 private:
1365 	void							init							(void);
1366 
1367 	int								getNumIterations				(void) const;
1368 	IterationConfig					getIteration					(int ndx) const;
1369 
1370 	const SizeType					m_sizeType;
1371 	const deUint32					m_filter;
1372 
1373 	std::vector<IterationConfig>	m_iterations;
1374 };
1375 
1376 
TextureBorderClampFormatCase(Context & context,const char * name,const char * description,deUint32 texFormat,tcu::Sampler::DepthStencilMode mode,StateType stateType,SizeType sizeType,deUint32 filter,SamplingFunction samplingFunction)1377 TextureBorderClampFormatCase::TextureBorderClampFormatCase	(Context&						context,
1378 															 const char*					name,
1379 															 const char*					description,
1380 															 deUint32						texFormat,
1381 															 tcu::Sampler::DepthStencilMode	mode,
1382 															 StateType						stateType,
1383 															 SizeType						sizeType,
1384 															 deUint32						filter,
1385 															 SamplingFunction				samplingFunction)
1386 	: TextureBorderClampTest(context,
1387 							 name,
1388 							 description,
1389 							 texFormat,
1390 							 mode,
1391 							 stateType,
1392 							 (sizeType == SIZE_POT) ? (32) : (17),
1393 							 (sizeType == SIZE_POT) ? (16) : (31),
1394 							 samplingFunction)
1395 	, m_sizeType			(sizeType)
1396 	, m_filter				(filter)
1397 {
1398 	if (m_sizeType == SIZE_POT)
1399 		DE_ASSERT(deIsPowerOfTwo32(m_texWidth) && deIsPowerOfTwo32(m_texHeight));
1400 	else
1401 		DE_ASSERT(!deIsPowerOfTwo32(m_texWidth) && !deIsPowerOfTwo32(m_texHeight));
1402 
1403 	if (glu::isCompressedFormat(texFormat))
1404 	{
1405 		const tcu::CompressedTexFormat	compressedFormat	= glu::mapGLCompressedTexFormat(texFormat);
1406 		const tcu::IVec3				blockPixelSize		= tcu::getBlockPixelSize(compressedFormat);
1407 
1408 		// is (not) multiple of a block size
1409 		if (m_sizeType == SIZE_POT)
1410 			DE_ASSERT((m_texWidth % blockPixelSize.x()) == 0 && (m_texHeight % blockPixelSize.y()) == 0);
1411 		else
1412 			DE_ASSERT((m_texWidth % blockPixelSize.x()) != 0 && (m_texHeight % blockPixelSize.y()) != 0);
1413 
1414 		DE_UNREF(blockPixelSize);
1415 	}
1416 }
1417 
init(void)1418 void TextureBorderClampFormatCase::init (void)
1419 {
1420 	TextureBorderClampTest::init();
1421 
1422 	// \note TextureBorderClampTest::init() creates texture
1423 	const tcu::TextureFormat		texFormat		= tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode);
1424 	const tcu::TextureFormatInfo	texFormatInfo	= tcu::getTextureFormatInfo(texFormat);
1425 
1426 	// iterations
1427 
1428 	{
1429 		IterationConfig iteration;
1430 		iteration.p0			= tcu::Vec2(-1.5f, -3.0f);
1431 		iteration.p1			= tcu::Vec2( 1.5f,  2.5f);
1432 		iteration.borderColor	= mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.3f, 0.7f, 0.2f, 0.5f));
1433 		m_iterations.push_back(iteration);
1434 	}
1435 	{
1436 		IterationConfig iteration;
1437 		iteration.p0			= tcu::Vec2(-0.5f, 0.75f);
1438 		iteration.p1			= tcu::Vec2(0.25f, 1.25f);
1439 		iteration.borderColor	= mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.9f, 0.2f, 0.4f, 0.6f));
1440 		m_iterations.push_back(iteration);
1441 	}
1442 
1443 	// common parameters
1444 	for (int ndx = 0; ndx < (int)m_iterations.size(); ++ndx)
1445 	{
1446 		IterationConfig& iteration = m_iterations[ndx];
1447 
1448 		if (m_samplingFunction == SAMPLE_GATHER)
1449 		{
1450 			iteration.lookupScale	= tcu::Vec4(texFormatInfo.lookupScale.x());
1451 			iteration.lookupBias	= tcu::Vec4(texFormatInfo.lookupBias.x());
1452 		}
1453 		else
1454 		{
1455 			iteration.lookupScale	= texFormatInfo.lookupScale;
1456 			iteration.lookupBias	= texFormatInfo.lookupBias;
1457 		}
1458 
1459 		iteration.minFilter		= m_filter;
1460 		iteration.magFilter		= m_filter;
1461 		iteration.sWrapMode		= GL_CLAMP_TO_BORDER;
1462 		iteration.tWrapMode		= GL_CLAMP_TO_BORDER;
1463 		iteration.compareMode	= GL_NONE;
1464 		iteration.compareRef	= 0.0f;
1465 	}
1466 }
1467 
getNumIterations(void) const1468 int TextureBorderClampFormatCase::getNumIterations	(void) const
1469 {
1470 	return (int)m_iterations.size();
1471 }
1472 
getIteration(int ndx) const1473 TextureBorderClampTest::IterationConfig TextureBorderClampFormatCase::getIteration (int ndx) const
1474 {
1475 	return m_iterations[ndx];
1476 }
1477 
1478 class TextureBorderClampRangeClampCase : public TextureBorderClampTest
1479 {
1480 public:
1481 									TextureBorderClampRangeClampCase	(Context&						context,
1482 																		 const char*					name,
1483 																		 const char*					description,
1484 																		 deUint32						texFormat,
1485 																		 tcu::Sampler::DepthStencilMode	mode,
1486 																		 deUint32						filter);
1487 
1488 private:
1489 	void							init								(void);
1490 
1491 	int								getNumIterations					(void) const;
1492 	IterationConfig					getIteration						(int ndx) const;
1493 
1494 	const deUint32					m_filter;
1495 	std::vector<IterationConfig>	m_iterations;
1496 };
1497 
TextureBorderClampRangeClampCase(Context & context,const char * name,const char * description,deUint32 texFormat,tcu::Sampler::DepthStencilMode mode,deUint32 filter)1498 TextureBorderClampRangeClampCase::TextureBorderClampRangeClampCase	(Context&						context,
1499 																	 const char*					name,
1500 																	 const char*					description,
1501 																	 deUint32						texFormat,
1502 																	 tcu::Sampler::DepthStencilMode	mode,
1503 																	 deUint32						filter)
1504 	: TextureBorderClampTest(context, name, description, texFormat, mode, TextureBorderClampTest::STATE_TEXTURE_PARAM, 8, 32, SAMPLE_FILTER)
1505 	, m_filter				(filter)
1506 {
1507 }
1508 
init(void)1509 void TextureBorderClampRangeClampCase::init (void)
1510 {
1511 	TextureBorderClampTest::init();
1512 
1513 	const tcu::TextureFormat	texFormat		= tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode);
1514 	const bool					isDepth			= isDepthFormat(m_texFormat, m_sampleMode);
1515 	const bool					isFloat			= m_channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT;
1516 	const bool					isFixed			= m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
1517 	const bool					isPureInteger	= m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
1518 
1519 	if (isDepth || isFloat)
1520 	{
1521 		// infinities are commonly used values on depth/float borders
1522 		{
1523 			IterationConfig iteration;
1524 			iteration.p0			= tcu::Vec2(-1.2f, -3.0f);
1525 			iteration.p1			= tcu::Vec2( 1.2f,  2.5f);
1526 			iteration.borderColor	= rr::GenericVec4(tcu::Vec4(std::numeric_limits<float>::infinity()));
1527 			iteration.lookupScale	= tcu::Vec4(0.5f); // scale & bias to [0.25, 0.5] range to make out-of-range values visible
1528 			iteration.lookupBias	= tcu::Vec4(0.25f);
1529 			iteration.description	= "border value infinity";
1530 			m_iterations.push_back(iteration);
1531 		}
1532 		{
1533 			IterationConfig iteration;
1534 			iteration.p0			= tcu::Vec2(-0.25f, -0.75f);
1535 			iteration.p1			= tcu::Vec2( 2.25f,  1.25f);
1536 			iteration.borderColor	= rr::GenericVec4(tcu::Vec4(-std::numeric_limits<float>::infinity()));
1537 			iteration.lookupScale	= tcu::Vec4(0.5f);
1538 			iteration.lookupBias	= tcu::Vec4(0.25f);
1539 			iteration.description	= "border value negative infinity";
1540 			m_iterations.push_back(iteration);
1541 		}
1542 	}
1543 	else if (isPureInteger)
1544 	{
1545 		const tcu::IVec4			numBits		= tcu::getTextureFormatBitDepth(texFormat);
1546 		const bool					isSigned	= m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER;
1547 
1548 		// can't overflow 32bit integers with 32bit integers
1549 		for (int ndx = 0; ndx < 4; ++ndx)
1550 			DE_ASSERT(numBits[ndx] == 0 || numBits[ndx] == 8 || numBits[ndx] == 16);
1551 
1552 		const tcu::IVec4	minValue		= getNBitIntegerVec4MinValue(isSigned, numBits);
1553 		const tcu::IVec4	maxValue		= getNBitIntegerVec4MaxValue(isSigned, numBits);
1554 		const tcu::IVec4	valueRange		= maxValue - minValue;
1555 		const tcu::IVec4	divSafeRange	((valueRange[0]==0) ? (1) : (valueRange[0]),
1556 											 (valueRange[1]==0) ? (1) : (valueRange[1]),
1557 											 (valueRange[2]==0) ? (1) : (valueRange[2]),
1558 											 (valueRange[3]==0) ? (1) : (valueRange[3]));
1559 
1560 		// format max
1561 		{
1562 			const tcu::IVec4 value = maxValue + tcu::IVec4(1);
1563 
1564 			IterationConfig iteration;
1565 			iteration.p0			= tcu::Vec2(-1.2f, -3.0f);
1566 			iteration.p1			= tcu::Vec2( 1.2f,  2.5f);
1567 			iteration.borderColor	= (isSigned) ? (rr::GenericVec4(value)) : (rr::GenericVec4(value.cast<deUint32>()));
1568 			iteration.lookupScale	= tcu::Vec4(0.5f) / divSafeRange.cast<float>();
1569 			iteration.lookupBias	= (isSigned) ? (tcu::Vec4(0.5f)) : (tcu::Vec4(0.25f));
1570 			iteration.description	= "border values one larger than maximum";
1571 			m_iterations.push_back(iteration);
1572 		}
1573 		// format min
1574 		if (isSigned)
1575 		{
1576 			const tcu::IVec4 value = minValue - tcu::IVec4(1);
1577 
1578 			IterationConfig iteration;
1579 			iteration.p0			= tcu::Vec2(-0.25f, -0.75f);
1580 			iteration.p1			= tcu::Vec2( 2.25f,  1.25f);
1581 			iteration.borderColor	= rr::GenericVec4(value);
1582 			iteration.lookupScale	= tcu::Vec4(0.5f) / divSafeRange.cast<float>();
1583 			iteration.lookupBias	= tcu::Vec4(0.5f);
1584 			iteration.description	= "border values one less than minimum";
1585 			m_iterations.push_back(iteration);
1586 		}
1587 		// (u)int32 max
1588 		{
1589 			const tcu::IVec4 value = (isSigned) ? (tcu::IVec4(std::numeric_limits<deInt32>::max())) : (tcu::IVec4(std::numeric_limits<deUint32>::max()));
1590 
1591 			IterationConfig iteration;
1592 			iteration.p0			= tcu::Vec2(-1.6f, -2.1f);
1593 			iteration.p1			= tcu::Vec2( 1.2f,  3.5f);
1594 			iteration.borderColor	= (isSigned) ? (rr::GenericVec4(value)) : (rr::GenericVec4(value.cast<deUint32>()));
1595 			iteration.lookupScale	= tcu::Vec4(0.5f) / divSafeRange.cast<float>();
1596 			iteration.lookupBias	= tcu::Vec4(0.25f);
1597 			iteration.description	= "border values 32-bit maximum";
1598 			m_iterations.push_back(iteration);
1599 		}
1600 		// int32 min
1601 		if (isSigned)
1602 		{
1603 			const tcu::IVec4 value = tcu::IVec4(std::numeric_limits<deInt32>::min());
1604 
1605 			IterationConfig iteration;
1606 			iteration.p0			= tcu::Vec2(-2.6f, -4.0f);
1607 			iteration.p1			= tcu::Vec2( 1.1f,  1.5f);
1608 			iteration.borderColor	= rr::GenericVec4(value);
1609 			iteration.lookupScale	= tcu::Vec4(0.5f) / divSafeRange.cast<float>();
1610 			iteration.lookupBias	= tcu::Vec4(0.25f);
1611 			iteration.description	= "border values 0";
1612 			m_iterations.push_back(iteration);
1613 		}
1614 	}
1615 	else if (isFixed)
1616 	{
1617 		const bool		isSigned	= m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
1618 		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
1619 		const tcu::Vec4	lookupScale	= (isSigned) ? (tcu::Vec4(0.25f))   : (tcu::Vec4(0.5f));
1620 
1621 		{
1622 			IterationConfig iteration;
1623 			iteration.p0			= tcu::Vec2(-1.2f, -3.0f);
1624 			iteration.p1			= tcu::Vec2( 1.2f,  2.5f);
1625 			iteration.borderColor	= mapToFormatColorUnits(texFormat, tcu::Vec4(1.1f, 1.3f, 2.2f, 1.3f));
1626 			iteration.lookupScale	= lookupScale;
1627 			iteration.lookupBias	= lookupBias;
1628 			iteration.description	= "border values larger than maximum";
1629 			m_iterations.push_back(iteration);
1630 		}
1631 		{
1632 			IterationConfig iteration;
1633 			iteration.p0			= tcu::Vec2(-0.25f, -0.75f);
1634 			iteration.p1			= tcu::Vec2( 2.25f,  1.25f);
1635 			iteration.borderColor	= mapToFormatColorUnits(texFormat, tcu::Vec4(-0.2f, -0.9f, -2.4f, -0.6f));
1636 			iteration.lookupScale	= lookupScale;
1637 			iteration.lookupBias	= lookupBias;
1638 			iteration.description	= "border values less than minimum";
1639 			m_iterations.push_back(iteration);
1640 		}
1641 	}
1642 	else
1643 		DE_ASSERT(false);
1644 
1645 	// common parameters
1646 	for (int ndx = 0; ndx < (int)m_iterations.size(); ++ndx)
1647 	{
1648 		IterationConfig& iteration = m_iterations[ndx];
1649 
1650 		iteration.minFilter		= m_filter;
1651 		iteration.magFilter		= m_filter;
1652 		iteration.sWrapMode		= GL_CLAMP_TO_BORDER;
1653 		iteration.tWrapMode		= GL_CLAMP_TO_BORDER;
1654 		iteration.compareMode	= GL_NONE;
1655 		iteration.compareRef	= 0.0f;
1656 	}
1657 }
1658 
getNumIterations(void) const1659 int TextureBorderClampRangeClampCase::getNumIterations	(void) const
1660 {
1661 	return (int)m_iterations.size();
1662 }
1663 
getIteration(int ndx) const1664 TextureBorderClampTest::IterationConfig TextureBorderClampRangeClampCase::getIteration (int ndx) const
1665 {
1666 	return m_iterations[ndx];
1667 }
1668 
1669 class TextureBorderClampPerAxisCase2D : public TextureBorderClampTest
1670 {
1671 public:
1672 									TextureBorderClampPerAxisCase2D	(Context&						context,
1673 																	 const char*					name,
1674 																	 const char*					description,
1675 																	 deUint32						texFormat,
1676 																	 tcu::Sampler::DepthStencilMode	mode,
1677 																	 SizeType						sizeType,
1678 																	 deUint32						filter,
1679 																	 deUint32						texSWrap,
1680 																	 deUint32						texTWrap,
1681 																	 SamplingFunction				samplingFunction);
1682 
1683 private:
1684 	void							init							(void);
1685 
1686 	int								getNumIterations				(void) const;
1687 	IterationConfig					getIteration					(int ndx) const;
1688 
1689 	const deUint32					m_texSWrap;
1690 	const deUint32					m_texTWrap;
1691 	const deUint32					m_filter;
1692 
1693 	std::vector<IterationConfig>	m_iterations;
1694 };
1695 
TextureBorderClampPerAxisCase2D(Context & context,const char * name,const char * description,deUint32 texFormat,tcu::Sampler::DepthStencilMode mode,SizeType sizeType,deUint32 filter,deUint32 texSWrap,deUint32 texTWrap,SamplingFunction samplingFunction)1696 TextureBorderClampPerAxisCase2D::TextureBorderClampPerAxisCase2D (Context&							context,
1697 																  const char*						name,
1698 																  const char*						description,
1699 																  deUint32							texFormat,
1700 																  tcu::Sampler::DepthStencilMode	mode,
1701 																  SizeType							sizeType,
1702 																  deUint32							filter,
1703 																  deUint32							texSWrap,
1704 																  deUint32							texTWrap,
1705 																  SamplingFunction					samplingFunction)
1706 	: TextureBorderClampTest(context,
1707 							 name,
1708 							 description,
1709 							 texFormat,
1710 							 mode,
1711 							 TextureBorderClampTest::STATE_TEXTURE_PARAM,
1712 							 (sizeType == SIZE_POT) ? (16) : (7),
1713 							 (sizeType == SIZE_POT) ? (8) : (9),
1714 							 samplingFunction)
1715 	, m_texSWrap			(texSWrap)
1716 	, m_texTWrap			(texTWrap)
1717 	, m_filter				(filter)
1718 {
1719 }
1720 
init(void)1721 void TextureBorderClampPerAxisCase2D::init (void)
1722 {
1723 	TextureBorderClampTest::init();
1724 
1725 	// \note TextureBorderClampTest::init() creates texture
1726 	const tcu::TextureFormat		texFormat		= tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode);
1727 	const tcu::TextureFormatInfo	texFormatInfo	= tcu::getTextureFormatInfo(texFormat);
1728 
1729 	IterationConfig iteration;
1730 	iteration.p0			= tcu::Vec2(-0.25f, -0.75f);
1731 	iteration.p1			= tcu::Vec2( 2.25f,  1.25f);
1732 	iteration.borderColor	= mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.4f, 0.9f, 0.1f, 0.2f));
1733 
1734 	if (m_samplingFunction == SAMPLE_GATHER)
1735 	{
1736 		iteration.lookupScale	= tcu::Vec4(texFormatInfo.lookupScale.x());
1737 		iteration.lookupBias	= tcu::Vec4(texFormatInfo.lookupBias.x());
1738 	}
1739 	else
1740 	{
1741 		iteration.lookupScale	= texFormatInfo.lookupScale;
1742 		iteration.lookupBias	= texFormatInfo.lookupBias;
1743 	}
1744 
1745 	iteration.minFilter		= m_filter;
1746 	iteration.magFilter		= m_filter;
1747 	iteration.sWrapMode		= m_texSWrap;
1748 	iteration.tWrapMode		= m_texTWrap;
1749 	iteration.compareMode	= GL_NONE;
1750 	iteration.compareRef	= 0.0f;
1751 
1752 	m_iterations.push_back(iteration);
1753 }
1754 
getNumIterations(void) const1755 int TextureBorderClampPerAxisCase2D::getNumIterations	(void) const
1756 {
1757 	return (int)m_iterations.size();
1758 }
1759 
getIteration(int ndx) const1760 TextureBorderClampTest::IterationConfig TextureBorderClampPerAxisCase2D::getIteration (int ndx) const
1761 {
1762 	return m_iterations[ndx];
1763 }
1764 
1765 class TextureBorderClampDepthCompareCase : public TextureBorderClampTest
1766 {
1767 public:
1768 									TextureBorderClampDepthCompareCase	(Context&			context,
1769 																		 const char*		name,
1770 																		 const char*		description,
1771 																		 deUint32			texFormat,
1772 																		 SizeType			sizeType,
1773 																		 deUint32			filter,
1774 																		 SamplingFunction	samplingFunction);
1775 
1776 private:
1777 	void							init								(void);
1778 
1779 	int								getNumIterations					(void) const;
1780 	IterationConfig					getIteration						(int ndx) const;
1781 
1782 	const deUint32					m_filter;
1783 	std::vector<IterationConfig>	m_iterations;
1784 };
1785 
TextureBorderClampDepthCompareCase(Context & context,const char * name,const char * description,deUint32 texFormat,SizeType sizeType,deUint32 filter,SamplingFunction samplingFunction)1786 TextureBorderClampDepthCompareCase::TextureBorderClampDepthCompareCase (Context&			context,
1787 																		const char*			name,
1788 																		const char*			description,
1789 																		deUint32			texFormat,
1790 																		SizeType			sizeType,
1791 																		deUint32			filter,
1792 																		SamplingFunction	samplingFunction)
1793 	: TextureBorderClampTest(context,
1794 							 name,
1795 							 description,
1796 							 texFormat,
1797 							 tcu::Sampler::MODE_DEPTH,
1798 							 TextureBorderClampTest::STATE_TEXTURE_PARAM,
1799 							 (sizeType == SIZE_POT) ? (32) : (13),
1800 							 (sizeType == SIZE_POT) ? (16) : (17),
1801 							 samplingFunction,
1802 							 FLAG_USE_SHADOW_SAMPLER)
1803 	, m_filter				(filter)
1804 {
1805 }
1806 
init(void)1807 void TextureBorderClampDepthCompareCase::init (void)
1808 {
1809 	TextureBorderClampTest::init();
1810 
1811 	// 0.5 <= 0.7
1812 	{
1813 		IterationConfig iteration;
1814 		iteration.p0			= tcu::Vec2(-0.15f, -0.35f);
1815 		iteration.p1			= tcu::Vec2( 1.25f,  1.1f);
1816 		iteration.borderColor	= rr::GenericVec4(tcu::Vec4(0.7f, 0.0f, 0.0f, 0.0f));
1817 		iteration.description	= "Border color in [0, 1] range";
1818 		iteration.compareMode	= GL_LEQUAL;
1819 		iteration.compareRef	= 0.5f;
1820 		m_iterations.push_back(iteration);
1821 	}
1822 
1823 	// 1.5 <= 1.0
1824 	{
1825 		IterationConfig iteration;
1826 		iteration.p0			= tcu::Vec2(-0.15f, -0.35f);
1827 		iteration.p1			= tcu::Vec2( 1.25f,  1.1f);
1828 		iteration.borderColor	= rr::GenericVec4(tcu::Vec4(1.5f, 0.0f, 0.0f, 0.0f));
1829 		iteration.description	= "Border color > 1, should be clamped";
1830 		iteration.compareMode	= GL_LEQUAL;
1831 		iteration.compareRef	= 1.0f;
1832 		m_iterations.push_back(iteration);
1833 	}
1834 
1835 	// -0.5 >= 0.0
1836 	{
1837 		IterationConfig iteration;
1838 		iteration.p0			= tcu::Vec2(-0.15f, -0.35f);
1839 		iteration.p1			= tcu::Vec2( 1.25f,  1.1f);
1840 		iteration.borderColor	= rr::GenericVec4(tcu::Vec4(-0.5f, 0.0f, 0.0f, 0.0f));
1841 		iteration.description	= "Border color < 0, should be clamped";
1842 		iteration.compareMode	= GL_GEQUAL;
1843 		iteration.compareRef	= 0.0f;
1844 		m_iterations.push_back(iteration);
1845 	}
1846 
1847 	// inf < 1.25
1848 	{
1849 		IterationConfig iteration;
1850 		iteration.p0			= tcu::Vec2(-0.15f, -0.35f);
1851 		iteration.p1			= tcu::Vec2( 1.25f,  1.1f);
1852 		iteration.borderColor	= rr::GenericVec4(tcu::Vec4(std::numeric_limits<float>::infinity(), 0.0f, 0.0f, 0.0f));
1853 		iteration.description	= "Border color == inf, should be clamped; ref > 1";
1854 		iteration.compareMode	= GL_LESS;
1855 		iteration.compareRef	= 1.25f;
1856 		m_iterations.push_back(iteration);
1857 	}
1858 
1859 	// -inf > -0.5
1860 	{
1861 		IterationConfig iteration;
1862 		iteration.p0			= tcu::Vec2(-0.15f, -0.35f);
1863 		iteration.p1			= tcu::Vec2( 1.25f,  1.1f);
1864 		iteration.borderColor	= rr::GenericVec4(tcu::Vec4(-std::numeric_limits<float>::infinity(), 0.0f, 0.0f, 0.0f));
1865 		iteration.description	= "Border color == inf, should be clamped; ref < 0";
1866 		iteration.compareMode	= GL_GREATER;
1867 		iteration.compareRef	= -0.5f;
1868 		m_iterations.push_back(iteration);
1869 	}
1870 
1871 	// common parameters
1872 	for (int ndx = 0; ndx < (int)m_iterations.size(); ++ndx)
1873 	{
1874 		IterationConfig& iteration = m_iterations[ndx];
1875 
1876 		iteration.lookupScale	= tcu::Vec4(1.0);
1877 		iteration.lookupBias	= tcu::Vec4(0.0);
1878 		iteration.minFilter		= m_filter;
1879 		iteration.magFilter		= m_filter;
1880 		iteration.sWrapMode		= GL_CLAMP_TO_BORDER;
1881 		iteration.tWrapMode		= GL_CLAMP_TO_BORDER;
1882 	}
1883 }
1884 
getNumIterations(void) const1885 int TextureBorderClampDepthCompareCase::getNumIterations	(void) const
1886 {
1887 	return (int)m_iterations.size();
1888 }
1889 
getIteration(int ndx) const1890 TextureBorderClampTest::IterationConfig TextureBorderClampDepthCompareCase::getIteration (int ndx) const
1891 {
1892 	return m_iterations[ndx];
1893 }
1894 
1895 class TextureBorderClampUnusedChannelCase : public TextureBorderClampTest
1896 {
1897 public:
1898 									TextureBorderClampUnusedChannelCase	(Context&						context,
1899 																		 const char*					name,
1900 																		 const char*					description,
1901 																		 deUint32						texFormat,
1902 																		 tcu::Sampler::DepthStencilMode	depthStencilMode);
1903 
1904 private:
1905 	void							init								(void);
1906 
1907 	int								getNumIterations					(void) const;
1908 	IterationConfig					getIteration						(int ndx) const;
1909 
1910 	std::vector<IterationConfig>	m_iterations;
1911 };
1912 
TextureBorderClampUnusedChannelCase(Context & context,const char * name,const char * description,deUint32 texFormat,tcu::Sampler::DepthStencilMode depthStencilMode)1913 TextureBorderClampUnusedChannelCase::TextureBorderClampUnusedChannelCase (Context&							context,
1914 																		  const char*						name,
1915 																		  const char*						description,
1916 																		  deUint32							texFormat,
1917 																		  tcu::Sampler::DepthStencilMode	depthStencilMode)
1918 	: TextureBorderClampTest(context,
1919 							 name,
1920 							 description,
1921 							 texFormat,
1922 							 depthStencilMode,
1923 							 TextureBorderClampTest::STATE_TEXTURE_PARAM,
1924 							 8,
1925 							 8,
1926 							 SAMPLE_FILTER)
1927 {
1928 }
1929 
selectComponents(const rr::GenericVec4 & trueComponents,const rr::GenericVec4 & falseComponents,const tcu::BVec4 & m)1930 static rr::GenericVec4 selectComponents (const rr::GenericVec4& trueComponents, const rr::GenericVec4& falseComponents, const tcu::BVec4& m)
1931 {
1932 	return rr::GenericVec4(tcu::select(trueComponents.get<deUint32>(), falseComponents.get<deUint32>(), m));
1933 }
1934 
init(void)1935 void TextureBorderClampUnusedChannelCase::init (void)
1936 {
1937 	TextureBorderClampTest::init();
1938 
1939 	// \note TextureBorderClampTest::init() creates texture
1940 	const tcu::TextureFormat		texFormat			= tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode);
1941 	const tcu::TextureFormatInfo	texFormatInfo		= tcu::getTextureFormatInfo(texFormat);
1942 	const tcu::BVec4				channelMask			= tcu::getTextureFormatChannelMask(texFormat);
1943 	const float						maxChannelValue		= (channelMask[0]) ? (texFormatInfo.valueMax[0])
1944 														: (channelMask[1]) ? (texFormatInfo.valueMax[1])
1945 														: (channelMask[2]) ? (texFormatInfo.valueMax[2])
1946 														:                    (texFormatInfo.valueMax[3]);
1947 
1948 	const rr::GenericVec4			effectiveColors		= mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.6f));
1949 	rr::GenericVec4					nonEffectiveColors;
1950 
1951 	switch (m_channelClass)
1952 	{
1953 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1954 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1955 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1956 			nonEffectiveColors = rr::GenericVec4(tcu::Vec4(maxChannelValue * 0.8f));
1957 			break;
1958 
1959 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1960 			nonEffectiveColors = rr::GenericVec4(tcu::Vec4(maxChannelValue * 0.8f).cast<deInt32>());
1961 			break;
1962 
1963 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1964 			nonEffectiveColors = rr::GenericVec4(tcu::Vec4(maxChannelValue * 0.8f).cast<deUint32>());
1965 			break;
1966 		default:
1967 			DE_ASSERT(false);
1968 	}
1969 
1970 	IterationConfig iteration;
1971 	iteration.p0			= tcu::Vec2(-0.25f, -0.75f);
1972 	iteration.p1			= tcu::Vec2( 2.25f,  1.25f);
1973 	iteration.borderColor	= selectComponents(effectiveColors, nonEffectiveColors, channelMask);
1974 	iteration.lookupScale	= texFormatInfo.lookupScale;
1975 	iteration.lookupBias	= texFormatInfo.lookupBias;
1976 	iteration.minFilter		= GL_NEAREST;
1977 	iteration.magFilter		= GL_NEAREST;
1978 	iteration.sWrapMode		= GL_CLAMP_TO_BORDER;
1979 	iteration.tWrapMode		= GL_CLAMP_TO_BORDER;
1980 	iteration.compareMode	= GL_NONE;
1981 	iteration.compareRef	= 0.0f;
1982 	iteration.description	= "Setting values to unused border color components";
1983 
1984 	m_iterations.push_back(iteration);
1985 }
1986 
getNumIterations(void) const1987 int TextureBorderClampUnusedChannelCase::getNumIterations	(void) const
1988 {
1989 	return (int)m_iterations.size();
1990 }
1991 
getIteration(int ndx) const1992 TextureBorderClampTest::IterationConfig TextureBorderClampUnusedChannelCase::getIteration (int ndx) const
1993 {
1994 	return m_iterations[ndx];
1995 }
1996 
1997 class TextureBorderClampPerAxisCase3D : public TestCase
1998 {
1999 public:
2000 														TextureBorderClampPerAxisCase3D	(Context&		context,
2001 																						 const char*	name,
2002 																						 const char*	description,
2003 																						 deUint32		texFormat,
2004 																						 SizeType		size,
2005 																						 deUint32		filter,
2006 																						 deUint32		sWrap,
2007 																						 deUint32		tWrap,
2008 																						 deUint32		rWrap);
2009 
2010 private:
2011 	void												init							(void);
2012 	void												deinit							(void);
2013 	IterateResult										iterate							(void);
2014 
2015 	void												renderTo						(tcu::Surface&									surface,
2016 																						 const glu::TextureTestUtil::ReferenceParams&	samplerParams);
2017 
2018 	void												logParams						(const glu::TextureTestUtil::ReferenceParams&	samplerParams);
2019 
2020 	void												verifyImage						(const tcu::Surface&							image,
2021 																						 const glu::TextureTestUtil::ReferenceParams&	samplerParams);
2022 
2023 	glu::TextureTestUtil::ReferenceParams				getSamplerParams				(void) const;
2024 	deUint32											getCaseSeed						(void) const;
2025 
2026 	enum
2027 	{
2028 		VIEWPORT_WIDTH		= 128,
2029 		VIEWPORT_HEIGHT		= 128,
2030 	};
2031 
2032 	const deUint32										m_texFormat;
2033 	const tcu::TextureChannelClass						m_channelClass;
2034 	const tcu::IVec3									m_size;
2035 	const deUint32										m_filter;
2036 	const deUint32										m_sWrap;
2037 	const deUint32										m_tWrap;
2038 	const deUint32										m_rWrap;
2039 
2040 	de::MovePtr<glu::Texture3D>							m_texture;
2041 	de::MovePtr<gls::TextureTestUtil::TextureRenderer>	m_renderer;
2042 
2043 	rr::GenericVec4										m_borderColor;
2044 	std::vector<float>									m_texCoords;
2045 	tcu::Vec4											m_lookupScale;
2046 	tcu::Vec4											m_lookupBias;
2047 };
2048 
TextureBorderClampPerAxisCase3D(Context & context,const char * name,const char * description,deUint32 texFormat,SizeType size,deUint32 filter,deUint32 sWrap,deUint32 tWrap,deUint32 rWrap)2049 TextureBorderClampPerAxisCase3D::TextureBorderClampPerAxisCase3D (Context&		context,
2050 																  const char*	name,
2051 																  const char*	description,
2052 																  deUint32		texFormat,
2053 																  SizeType		size,
2054 																  deUint32		filter,
2055 																  deUint32		sWrap,
2056 																  deUint32		tWrap,
2057 																  deUint32		rWrap)
2058 	: TestCase			(context, name, description)
2059 	, m_texFormat		(texFormat)
2060 	, m_channelClass	(getFormatChannelClass(texFormat, tcu::Sampler::MODE_LAST))
2061 	, m_size			((size == SIZE_POT) ? (tcu::IVec3(8, 16, 4)) : (tcu::IVec3(13, 5, 7)))
2062 	, m_filter			(filter)
2063 	, m_sWrap			(sWrap)
2064 	, m_tWrap			(tWrap)
2065 	, m_rWrap			(rWrap)
2066 {
2067 }
2068 
init(void)2069 void TextureBorderClampPerAxisCase3D::init (void)
2070 {
2071 	auto		ctxType						= m_context.getRenderContext().getType();
2072 	const bool	isES32orGL45				= glu::contextSupports(ctxType, glu::ApiType::es(3, 2)) ||
2073 											  glu::contextSupports(ctxType, glu::ApiType::core(4, 5));
2074 	const glu::GLSLVersion	glslVersion		= glu::getContextTypeGLSLVersion(ctxType);
2075 
2076 	if (!isES32orGL45 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_border_clamp"))
2077 		throw tcu::NotSupportedError("Test requires GL_EXT_texture_border_clamp extension");
2078 
2079 	if (glu::isCompressedFormat(m_texFormat)													&&
2080 		!isES32orGL45																			&&
2081 		tcu::isAstcFormat(glu::mapGLCompressedTexFormat(m_texFormat))							&&
2082 		!m_context.getContextInfo().isExtensionSupported("GL_KHR_texture_compression_astc_ldr"))
2083 	{
2084 		throw tcu::NotSupportedError("Test requires GL_KHR_texture_compression_astc_ldr extension");
2085 	}
2086 	if (m_texFormat == GL_BGRA && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_format_BGRA8888"))
2087 		throw tcu::NotSupportedError("Test requires GL_EXT_texture_format_BGRA8888 extension");
2088 	if (m_context.getRenderTarget().getWidth() < VIEWPORT_WIDTH ||
2089 		m_context.getRenderTarget().getHeight() < VIEWPORT_HEIGHT)
2090 	{
2091 		throw tcu::NotSupportedError("Test requires " + de::toString<int>(VIEWPORT_WIDTH) + "x" + de::toString<int>(VIEWPORT_HEIGHT) + " viewport");
2092 	}
2093 
2094 	// resources
2095 	m_texture = genDefaultTexture<glu::Texture3D>(m_context.getRenderContext(), m_context.getContextInfo(), m_texFormat, m_size);
2096 	m_renderer = de::MovePtr<gls::TextureTestUtil::TextureRenderer>(new gls::TextureTestUtil::TextureRenderer(m_context.getRenderContext(), m_testCtx.getLog(), glslVersion, glu::PRECISION_HIGHP));
2097 
2098 	// texture info
2099 	m_testCtx.getLog()	<< tcu::TestLog::Message
2100 						<< "Created 3D texture with format " << glu::getTextureFormatName(m_texFormat)
2101 						<< ", size (" << m_texture->getRefTexture().getWidth() << ", " << m_texture->getRefTexture().getHeight() << ", " << m_texture->getRefTexture().getDepth() << ")\n"
2102 						<< tcu::TestLog::EndMessage;
2103 
2104 	// tex coord
2105 	{
2106 		m_testCtx.getLog()	<< tcu::TestLog::Message
2107 							<< "Setting tex coords bottom-left: (-1, -1, -1.5), top-right (2, 2, 2.5)\n"
2108 							<< tcu::TestLog::EndMessage;
2109 
2110 		m_texCoords.resize(4*3);
2111 
2112 		m_texCoords[0] = -1.0f; m_texCoords[ 1] = -1.0f; m_texCoords[ 2] = -1.5f;
2113 		m_texCoords[3] = -1.0f; m_texCoords[ 4] =  2.0f; m_texCoords[ 5] = 0.5f;
2114 		m_texCoords[6] =  2.0f; m_texCoords[ 7] = -1.0f; m_texCoords[ 8] = 0.5f;
2115 		m_texCoords[9] =  2.0f; m_texCoords[10] =  2.0f; m_texCoords[11] =  2.5f;
2116 	}
2117 
2118 	// set render params
2119 	{
2120 		const tcu::TextureFormat		texFormat		= m_texture->getRefTexture().getFormat();
2121 		const tcu::TextureFormatInfo	texFormatInfo	= tcu::getTextureFormatInfo(texFormat);
2122 
2123 		m_borderColor	= mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.2f, 0.6f, 0.9f, 0.4f));
2124 
2125 		m_lookupScale	= texFormatInfo.lookupScale;
2126 		m_lookupBias	= texFormatInfo.lookupBias;
2127 	}
2128 }
2129 
deinit(void)2130 void TextureBorderClampPerAxisCase3D::deinit (void)
2131 {
2132 	m_texture.clear();
2133 	m_renderer.clear();
2134 }
2135 
iterate(void)2136 TextureBorderClampPerAxisCase3D::IterateResult TextureBorderClampPerAxisCase3D::iterate (void)
2137 {
2138 	tcu::Surface								renderedFrame		(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
2139 	const glu::TextureTestUtil::ReferenceParams	samplerParams		= getSamplerParams();
2140 
2141 	logParams(samplerParams);
2142 	renderTo(renderedFrame, samplerParams);
2143 	verifyImage(renderedFrame, samplerParams);
2144 
2145 	return STOP;
2146 }
2147 
logParams(const glu::TextureTestUtil::ReferenceParams & samplerParams)2148 void TextureBorderClampPerAxisCase3D::logParams (const glu::TextureTestUtil::ReferenceParams& samplerParams)
2149 {
2150 	const std::string	borderColorString	= (m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)   ? (de::toString(m_borderColor.get<deInt32>()))
2151 											: (m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) ? (de::toString(m_borderColor.get<deUint32>()))
2152 											:																  (de::toString(m_borderColor.get<float>()));
2153 
2154 	m_testCtx.getLog()	<< tcu::TestLog::Message
2155 						<< "Border color is " << borderColorString << "\n"
2156 						<< "Texture lookup bias: " << samplerParams.colorBias << "\n"
2157 						<< "Texture lookup scale: " << samplerParams.colorScale << "\n"
2158 						<< "Filter: " << glu::getTextureFilterName(m_filter) << "\n"
2159 						<< "Wrap mode: s = " << glu::getRepeatModeStr(m_sWrap)
2160 							<< ", t = " << glu::getRepeatModeStr(m_tWrap)
2161 							<< ", r = " << glu::getRepeatModeStr(m_rWrap) << "\n"
2162 						<< tcu::TestLog::EndMessage;
2163 }
2164 
renderTo(tcu::Surface & surface,const glu::TextureTestUtil::ReferenceParams & samplerParams)2165 void TextureBorderClampPerAxisCase3D::renderTo (tcu::Surface&									surface,
2166 												const glu::TextureTestUtil::ReferenceParams&	samplerParams)
2167 {
2168 	const glw::Functions&						gl			= m_context.getRenderContext().getFunctions();
2169 	const gls::TextureTestUtil::RandomViewport	viewport	(m_context.getRenderTarget(), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, getCaseSeed());
2170 
2171 	// Bind to unit 0.
2172 	gl.activeTexture(GL_TEXTURE0);
2173 	gl.bindTexture(GL_TEXTURE_3D, m_texture->getGLTexture());
2174 
2175 	// Setup filtering and wrap modes.
2176 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S,		glu::getGLWrapMode(samplerParams.sampler.wrapS));
2177 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T,		glu::getGLWrapMode(samplerParams.sampler.wrapT));
2178 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R,		glu::getGLWrapMode(samplerParams.sampler.wrapR));
2179 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER,	glu::getGLFilterMode(samplerParams.sampler.minFilter));
2180 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER,	glu::getGLFilterMode(samplerParams.sampler.magFilter));
2181 
2182 	switch (m_channelClass)
2183 	{
2184 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2185 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2186 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2187 			gl.texParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, m_borderColor.getAccess<float>());
2188 			break;
2189 
2190 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2191 			gl.texParameterIiv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, m_borderColor.getAccess<deInt32>());
2192 			break;
2193 
2194 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2195 			gl.texParameterIuiv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, m_borderColor.getAccess<deUint32>());
2196 			break;
2197 
2198 		default:
2199 			DE_ASSERT(false);
2200 	}
2201 
2202 	GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
2203 
2204 	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
2205 	m_renderer->renderQuad(0, &m_texCoords[0], samplerParams);
2206 	glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, surface.getAccess());
2207 }
2208 
verifyImage(const tcu::Surface & renderedFrame,const glu::TextureTestUtil::ReferenceParams & samplerParams)2209 void TextureBorderClampPerAxisCase3D::verifyImage (const tcu::Surface&							renderedFrame,
2210 												   const glu::TextureTestUtil::ReferenceParams&	samplerParams)
2211 {
2212 	const tcu::PixelFormat			pixelFormat			= m_context.getRenderTarget().getPixelFormat();
2213 	const int						colorErrorBits		= 2;
2214 	const tcu::IVec4				colorBits			= tcu::max(glu::TextureTestUtil::getBitsVec(pixelFormat) - tcu::IVec4(colorErrorBits), tcu::IVec4(0));
2215 	tcu::Surface					reference			(renderedFrame.getWidth(), renderedFrame.getHeight());
2216 	tcu::Surface					errorMask			(renderedFrame.getWidth(), renderedFrame.getHeight());
2217 	tcu::LodPrecision				lodPrecision;
2218 	tcu::LookupPrecision			lookupPrecision;
2219 	int								numFailedPixels;
2220 
2221 	lodPrecision.derivateBits		= 18;
2222 	lodPrecision.lodBits			= 5;
2223 
2224 	lookupPrecision.colorThreshold	= tcu::computeFixedPointThreshold(colorBits) / samplerParams.colorScale;
2225 	lookupPrecision.coordBits		= tcu::IVec3(20,20,0);
2226 	lookupPrecision.uvwBits			= tcu::IVec3(5,5,0);
2227 	lookupPrecision.colorMask		= glu::TextureTestUtil::getCompareMask(pixelFormat);
2228 
2229 	glu::TextureTestUtil::sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), m_texture->getRefTexture(), &m_texCoords[0], samplerParams);
2230 
2231 	numFailedPixels = glu::TextureTestUtil::computeTextureLookupDiff(renderedFrame.getAccess(), reference.getAccess(), errorMask.getAccess(), m_texture->getRefTexture(),
2232 																	 &m_texCoords[0], samplerParams, lookupPrecision, lodPrecision, m_testCtx.getWatchDog());
2233 
2234 	if (numFailedPixels > 0)
2235 		m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage;
2236 	m_testCtx.getLog()	<< tcu::TestLog::ImageSet("VerifyResult", "Verification result")
2237 						<< tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame);
2238 	if (numFailedPixels > 0)
2239 	{
2240 		m_testCtx.getLog()	<< tcu::TestLog::Image("Reference", "Ideal reference image", reference)
2241 							<< tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
2242 	}
2243 	m_testCtx.getLog() << tcu::TestLog::EndImageSet;
2244 
2245 	if (numFailedPixels == 0)
2246 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2247 	else
2248 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
2249 }
2250 
getSamplerParams(void) const2251 glu::TextureTestUtil::ReferenceParams TextureBorderClampPerAxisCase3D::getSamplerParams (void) const
2252 {
2253 	const tcu::TextureFormat				texFormat		= m_texture->getRefTexture().getFormat();
2254 	glu::TextureTestUtil::ReferenceParams	refParams		(glu::TextureTestUtil::TEXTURETYPE_3D);
2255 
2256 	refParams.sampler					= glu::mapGLSampler(m_sWrap, m_tWrap, m_rWrap, m_filter, m_filter);
2257 	refParams.sampler.borderColor		= m_borderColor;
2258 	refParams.lodMode					= glu::TextureTestUtil::LODMODE_EXACT;
2259 	refParams.samplerType				= glu::TextureTestUtil::getSamplerType(texFormat);
2260 	refParams.colorScale				= m_lookupScale;
2261 	refParams.colorBias					= m_lookupBias;
2262 
2263 	return refParams;
2264 }
2265 
getCaseSeed(void) const2266 deUint32 TextureBorderClampPerAxisCase3D::getCaseSeed (void) const
2267 {
2268 	tcu::SeedBuilder builder;
2269 	builder	<< std::string(getName())
2270 			<< m_texFormat
2271 			<< m_filter
2272 			<< m_sWrap
2273 			<< m_tWrap
2274 			<< m_rWrap
2275 			<< m_texture->getRefTexture().getWidth()
2276 			<< m_texture->getRefTexture().getHeight()
2277 			<< m_texture->getRefTexture().getDepth();
2278 	return builder.get();
2279 }
2280 
isFormatSupported(deUint32 format,bool isGL45)2281 static bool isFormatSupported(deUint32 format, bool isGL45)
2282 {
2283 	if (isGL45 && (format == GL_LUMINANCE || format == GL_ALPHA || format == GL_LUMINANCE_ALPHA))
2284 		return false;
2285 
2286 	return true;
2287 }
2288 
2289 } // anonymous
2290 
TextureBorderClampTests(Context & context,bool isGL45)2291 TextureBorderClampTests::TextureBorderClampTests (Context& context, bool isGL45)
2292 	: TestCaseGroup(context, "border_clamp", "EXT_texture_border_clamp tests")
2293 	, m_isGL45(isGL45)
2294 {
2295 }
2296 
~TextureBorderClampTests(void)2297 TextureBorderClampTests::~TextureBorderClampTests (void)
2298 {
2299 }
2300 
init(void)2301 void TextureBorderClampTests::init (void)
2302 {
2303 	static const struct
2304 	{
2305 		const char*									name;
2306 		deUint32									filter;
2307 		TextureBorderClampTest::SamplingFunction	sampling;
2308 	} s_filters[] =
2309 	{
2310 		{ "nearest",	GL_NEAREST,	TextureBorderClampTest::SAMPLE_FILTER	},
2311 		{ "linear",		GL_LINEAR,	TextureBorderClampTest::SAMPLE_FILTER	},
2312 		{ "gather",		GL_NEAREST,	TextureBorderClampTest::SAMPLE_GATHER	},
2313 	};
2314 
2315 	// .formats
2316 	{
2317 		static const struct
2318 		{
2319 			const char*						name;
2320 			deUint32						format;
2321 			tcu::Sampler::DepthStencilMode	mode;
2322 		} formats[] =
2323 		{
2324 			{ "luminance",									GL_LUMINANCE,									tcu::Sampler::MODE_LAST		},
2325 			{ "alpha",										GL_ALPHA,										tcu::Sampler::MODE_LAST		},
2326 			{ "luminance_alpha",							GL_LUMINANCE_ALPHA,								tcu::Sampler::MODE_LAST		},
2327 			{ "bgra",										GL_BGRA,										tcu::Sampler::MODE_LAST		},
2328 			{ "r8",											GL_R8,											tcu::Sampler::MODE_LAST		},
2329 			{ "r8_snorm",									GL_R8_SNORM,									tcu::Sampler::MODE_LAST		},
2330 			{ "rg8",										GL_RG8,											tcu::Sampler::MODE_LAST		},
2331 			{ "rg8_snorm",									GL_RG8_SNORM,									tcu::Sampler::MODE_LAST		},
2332 			{ "rgb8",										GL_RGB8,										tcu::Sampler::MODE_LAST		},
2333 			{ "rgb8_snorm",									GL_RGB8_SNORM,									tcu::Sampler::MODE_LAST		},
2334 			{ "rgb565",										GL_RGB565,										tcu::Sampler::MODE_LAST		},
2335 			{ "rgba4",										GL_RGBA4,										tcu::Sampler::MODE_LAST		},
2336 			{ "rgb5_a1",									GL_RGB5_A1,										tcu::Sampler::MODE_LAST		},
2337 			{ "rgba8",										GL_RGBA8,										tcu::Sampler::MODE_LAST		},
2338 			{ "rgba8_snorm",								GL_RGBA8_SNORM,									tcu::Sampler::MODE_LAST		},
2339 			{ "rgb10_a2",									GL_RGB10_A2,									tcu::Sampler::MODE_LAST		},
2340 			{ "rgb10_a2ui",									GL_RGB10_A2UI,									tcu::Sampler::MODE_LAST		},
2341 			{ "srgb8",										GL_SRGB8,										tcu::Sampler::MODE_LAST		},
2342 			{ "srgb8_alpha8",								GL_SRGB8_ALPHA8,								tcu::Sampler::MODE_LAST		},
2343 			{ "r16f",										GL_R16F,										tcu::Sampler::MODE_LAST		},
2344 			{ "rg16f",										GL_RG16F,										tcu::Sampler::MODE_LAST		},
2345 			{ "rgb16f",										GL_RGB16F,										tcu::Sampler::MODE_LAST		},
2346 			{ "rgba16f",									GL_RGBA16F,										tcu::Sampler::MODE_LAST		},
2347 			{ "r32f",										GL_R32F,										tcu::Sampler::MODE_LAST		},
2348 			{ "rg32f",										GL_RG32F,										tcu::Sampler::MODE_LAST		},
2349 			{ "rgb32f",										GL_RGB32F,										tcu::Sampler::MODE_LAST		},
2350 			{ "rgba32f",									GL_RGBA32F,										tcu::Sampler::MODE_LAST		},
2351 			{ "r11f_g11f_b10f",								GL_R11F_G11F_B10F,								tcu::Sampler::MODE_LAST		},
2352 			{ "rgb9_e5",									GL_RGB9_E5,										tcu::Sampler::MODE_LAST		},
2353 			{ "r8i",										GL_R8I,											tcu::Sampler::MODE_LAST		},
2354 			{ "r8ui",										GL_R8UI,										tcu::Sampler::MODE_LAST		},
2355 			{ "r16i",										GL_R16I,										tcu::Sampler::MODE_LAST		},
2356 			{ "r16ui",										GL_R16UI,										tcu::Sampler::MODE_LAST		},
2357 			{ "r32i",										GL_R32I,										tcu::Sampler::MODE_LAST		},
2358 			{ "r32ui",										GL_R32UI,										tcu::Sampler::MODE_LAST		},
2359 			{ "rg8i",										GL_RG8I,										tcu::Sampler::MODE_LAST		},
2360 			{ "rg8ui",										GL_RG8UI,										tcu::Sampler::MODE_LAST		},
2361 			{ "rg16i",										GL_RG16I,										tcu::Sampler::MODE_LAST		},
2362 			{ "rg16ui",										GL_RG16UI,										tcu::Sampler::MODE_LAST		},
2363 			{ "rg32i",										GL_RG32I,										tcu::Sampler::MODE_LAST		},
2364 			{ "rg32ui",										GL_RG32UI,										tcu::Sampler::MODE_LAST		},
2365 			{ "rgb8i",										GL_RGB8I,										tcu::Sampler::MODE_LAST		},
2366 			{ "rgb8ui",										GL_RGB8UI,										tcu::Sampler::MODE_LAST		},
2367 			{ "rgb16i",										GL_RGB16I,										tcu::Sampler::MODE_LAST		},
2368 			{ "rgb16ui",									GL_RGB16UI,										tcu::Sampler::MODE_LAST		},
2369 			{ "rgb32i",										GL_RGB32I,										tcu::Sampler::MODE_LAST		},
2370 			{ "rgb32ui",									GL_RGB32UI,										tcu::Sampler::MODE_LAST		},
2371 			{ "rgba8i",										GL_RGBA8I,										tcu::Sampler::MODE_LAST		},
2372 			{ "rgba8ui",									GL_RGBA8UI,										tcu::Sampler::MODE_LAST		},
2373 			{ "rgba16i",									GL_RGBA16I,										tcu::Sampler::MODE_LAST		},
2374 			{ "rgba16ui",									GL_RGBA16UI,									tcu::Sampler::MODE_LAST		},
2375 			{ "rgba32i",									GL_RGBA32I,										tcu::Sampler::MODE_LAST		},
2376 			{ "rgba32ui",									GL_RGBA32UI,									tcu::Sampler::MODE_LAST		},
2377 			{ "depth_component16",							GL_DEPTH_COMPONENT16,							tcu::Sampler::MODE_DEPTH	},
2378 			{ "depth_component24",							GL_DEPTH_COMPONENT24,							tcu::Sampler::MODE_DEPTH	},
2379 			{ "depth_component32f",							GL_DEPTH_COMPONENT32F,							tcu::Sampler::MODE_DEPTH	},
2380 			{ "stencil_index8",								GL_STENCIL_INDEX8,								tcu::Sampler::MODE_STENCIL	},
2381 			{ "depth24_stencil8_sample_depth",				GL_DEPTH24_STENCIL8,							tcu::Sampler::MODE_DEPTH	},
2382 			{ "depth32f_stencil8_sample_depth",				GL_DEPTH32F_STENCIL8,							tcu::Sampler::MODE_DEPTH	},
2383 			{ "depth24_stencil8_sample_stencil",			GL_DEPTH24_STENCIL8,							tcu::Sampler::MODE_STENCIL	},
2384 			{ "depth32f_stencil8_sample_stencil",			GL_DEPTH32F_STENCIL8,							tcu::Sampler::MODE_STENCIL	},
2385 			{ "compressed_r11_eac",							GL_COMPRESSED_R11_EAC,							tcu::Sampler::MODE_LAST		},
2386 			{ "compressed_signed_r11_eac",					GL_COMPRESSED_SIGNED_R11_EAC,					tcu::Sampler::MODE_LAST		},
2387 			{ "compressed_rg11_eac",						GL_COMPRESSED_RG11_EAC,							tcu::Sampler::MODE_LAST		},
2388 			{ "compressed_signed_rg11_eac",					GL_COMPRESSED_SIGNED_RG11_EAC,					tcu::Sampler::MODE_LAST		},
2389 			{ "compressed_rgb8_etc2",						GL_COMPRESSED_RGB8_ETC2,						tcu::Sampler::MODE_LAST		},
2390 			{ "compressed_srgb8_etc2",						GL_COMPRESSED_SRGB8_ETC2,						tcu::Sampler::MODE_LAST		},
2391 			{ "compressed_rgb8_punchthrough_alpha1_etc2",	GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,	tcu::Sampler::MODE_LAST		},
2392 			{ "compressed_srgb8_punchthrough_alpha1_etc2",	GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,	tcu::Sampler::MODE_LAST		},
2393 			{ "compressed_rgba8_etc2_eac",					GL_COMPRESSED_RGBA8_ETC2_EAC,					tcu::Sampler::MODE_LAST		},
2394 			{ "compressed_srgb8_alpha8_etc2_eac",			GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,			tcu::Sampler::MODE_LAST		},
2395 		};
2396 
2397 		tcu::TestCaseGroup* const formatsGroup = new tcu::TestCaseGroup(m_testCtx, "formats", "Format tests");
2398 		addChild(formatsGroup);
2399 
2400 		// .format
2401 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
2402 		{
2403 			const deUint32							format			= formats[formatNdx].format;
2404 			const tcu::Sampler::DepthStencilMode	sampleMode		= formats[formatNdx].mode;
2405 			const bool								isCompressed	= glu::isCompressedFormat(format);
2406 			const bool								coreFilterable	= isCoreFilterableFormat(format, sampleMode);
2407 			tcu::TestCaseGroup* const				formatGroup		= new tcu::TestCaseGroup(m_testCtx, formats[formatNdx].name, "Format test");
2408 
2409 			formatsGroup->addChild(formatGroup);
2410 
2411 			// .nearest
2412 			// .linear
2413 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx)
2414 			{
2415 				// [not-compressed]
2416 				// .size_pot
2417 				// .size_npot
2418 				// [compressed]
2419 				// .size_tile_multiple (also pot)
2420 				// .size_not_tile_multiple (also npot)
2421 				for (int sizeNdx = 0; sizeNdx < 2; ++sizeNdx)
2422 				{
2423 					const bool				isNpotCase		= (sizeNdx == 1);
2424 					const char* const		sizePotName		= (!isCompressed) ? ("size_pot") : ("size_tile_multiple");
2425 					const char* const		sizeNpotName	= (!isCompressed) ? ("size_npot") : ("size_not_tile_multiple");
2426 					const char* const		sizeName		= (isNpotCase) ? (sizeNpotName) : (sizePotName);
2427 					const SizeType			sizeType		= (isNpotCase) ? (SIZE_NPOT) : (SIZE_POT);
2428 					const std::string		caseName		= std::string() + s_filters[filterNdx].name + "_" + sizeName;
2429 					const deUint32			filter			= s_filters[filterNdx].filter;
2430 
2431 					if ((coreFilterable || !filterRequiresFilterability(filter)) && isFormatSupported(format, m_isGL45))
2432 						formatGroup->addChild(new TextureBorderClampFormatCase(m_context,
2433 																			   caseName.c_str(),
2434 																			   "",
2435 																			   format,
2436 																			   sampleMode,
2437 																			   TextureBorderClampFormatCase::STATE_TEXTURE_PARAM,
2438 																			   sizeType,
2439 																			   filter,
2440 																			   s_filters[filterNdx].sampling));
2441 				}
2442 			}
2443 		}
2444 	}
2445 
2446 	// .range_clamp
2447 	{
2448 		static const struct
2449 		{
2450 			const char*						name;
2451 			deUint32						format;
2452 			tcu::Sampler::DepthStencilMode	mode;
2453 		} formats[] =
2454 		{
2455 			{ "unorm_color",								GL_R8,					tcu::Sampler::MODE_LAST		},
2456 			{ "snorm_color",								GL_R8_SNORM,			tcu::Sampler::MODE_LAST		},
2457 			{ "float_color",								GL_RG32F,				tcu::Sampler::MODE_LAST		},
2458 			{ "int_color",									GL_R8I,					tcu::Sampler::MODE_LAST		},
2459 			{ "uint_color",									GL_R16UI,				tcu::Sampler::MODE_LAST		},
2460 			{ "srgb_color",									GL_SRGB8_ALPHA8,		tcu::Sampler::MODE_LAST		},
2461 			{ "unorm_depth",								GL_DEPTH_COMPONENT24,	tcu::Sampler::MODE_DEPTH	},
2462 			{ "float_depth",								GL_DEPTH_COMPONENT32F,	tcu::Sampler::MODE_DEPTH	},
2463 			{ "uint_stencil",								GL_STENCIL_INDEX8,		tcu::Sampler::MODE_STENCIL	},
2464 			{ "float_depth_uint_stencil_sample_depth",		GL_DEPTH32F_STENCIL8,	tcu::Sampler::MODE_DEPTH	},
2465 			{ "float_depth_uint_stencil_sample_stencil",	GL_DEPTH32F_STENCIL8,	tcu::Sampler::MODE_STENCIL	},
2466 			{ "unorm_depth_uint_stencil_sample_depth",		GL_DEPTH24_STENCIL8,	tcu::Sampler::MODE_DEPTH	},
2467 			{ "unorm_depth_uint_stencil_sample_stencil",	GL_DEPTH24_STENCIL8,	tcu::Sampler::MODE_STENCIL	},
2468 			{ "compressed_color",							GL_COMPRESSED_RG11_EAC,	tcu::Sampler::MODE_LAST		},
2469 		};
2470 
2471 		tcu::TestCaseGroup* const rangeClampGroup = new tcu::TestCaseGroup(m_testCtx, "range_clamp", "Range clamp tests");
2472 		addChild(rangeClampGroup);
2473 
2474 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
2475 		for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx)
2476 		{
2477 			const deUint32							format			= formats[formatNdx].format;
2478 			const tcu::Sampler::DepthStencilMode	sampleMode		= formats[formatNdx].mode;
2479 			const std::string						caseName		= std::string() + s_filters[filterNdx].name + "_" + formats[formatNdx].name;
2480 			const deUint32							filter			= s_filters[filterNdx].filter;
2481 			const bool								coreFilterable	= isCoreFilterableFormat(format, sampleMode);
2482 
2483 			if (s_filters[filterNdx].sampling == TextureBorderClampTest::SAMPLE_GATHER)
2484 				continue;
2485 
2486 			if (coreFilterable || !filterRequiresFilterability(filter))
2487 				rangeClampGroup->addChild(new TextureBorderClampRangeClampCase(m_context, caseName.c_str(), "", format, sampleMode, filter));
2488 		}
2489 	}
2490 
2491 	// .sampler
2492 	{
2493 		static const struct
2494 		{
2495 			const char*						name;
2496 			deUint32						format;
2497 			tcu::Sampler::DepthStencilMode	mode;
2498 		} formats[] =
2499 		{
2500 			{ "unorm_color",		GL_R8,					tcu::Sampler::MODE_LAST		},
2501 			{ "snorm_color",		GL_R8_SNORM,			tcu::Sampler::MODE_LAST		},
2502 			{ "float_color",		GL_RG32F,				tcu::Sampler::MODE_LAST		},
2503 			{ "int_color",			GL_R8I,					tcu::Sampler::MODE_LAST		},
2504 			{ "uint_color",			GL_R16UI,				tcu::Sampler::MODE_LAST		},
2505 			{ "unorm_depth",		GL_DEPTH_COMPONENT24,	tcu::Sampler::MODE_DEPTH	},
2506 			{ "float_depth",		GL_DEPTH_COMPONENT32F,	tcu::Sampler::MODE_DEPTH	},
2507 			{ "uint_stencil",		GL_STENCIL_INDEX8,		tcu::Sampler::MODE_STENCIL	},
2508 			{ "compressed_color",	GL_COMPRESSED_RG11_EAC,	tcu::Sampler::MODE_LAST		},
2509 		};
2510 
2511 		tcu::TestCaseGroup* const samplerGroup = new tcu::TestCaseGroup(m_testCtx, "sampler", "Sampler param tests");
2512 		addChild(samplerGroup);
2513 
2514 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
2515 		{
2516 			const deUint32							format		= formats[formatNdx].format;
2517 			const tcu::Sampler::DepthStencilMode	sampleMode	= formats[formatNdx].mode;
2518 			const char*								caseName	= formats[formatNdx].name;
2519 
2520 			samplerGroup->addChild(new TextureBorderClampFormatCase(m_context,
2521 																	caseName,
2522 																	"",
2523 																	format,
2524 																	sampleMode,
2525 																	TextureBorderClampFormatCase::STATE_SAMPLER_PARAM,
2526 																	SIZE_POT,
2527 																	GL_NEAREST,
2528 																	TextureBorderClampFormatCase::SAMPLE_FILTER));
2529 		}
2530 	}
2531 
2532 	// .per_axis_wrap_mode
2533 	{
2534 		static const struct
2535 		{
2536 			const char*						name;
2537 			bool							is3D;
2538 		} targets[] =
2539 		{
2540 			{ "texture_2d", false	},
2541 			{ "texture_3d", true	},
2542 		};
2543 		static const struct
2544 		{
2545 			const char*						name;
2546 			deUint32						format;
2547 			tcu::Sampler::DepthStencilMode	mode;
2548 			bool							supports3D;
2549 		} formats[] =
2550 		{
2551 			{ "unorm_color",		GL_RG8,						tcu::Sampler::MODE_LAST,	true	},
2552 			{ "snorm_color",		GL_RG8_SNORM,				tcu::Sampler::MODE_LAST,	true	},
2553 			{ "float_color",		GL_R32F,					tcu::Sampler::MODE_LAST,	true	},
2554 			{ "int_color",			GL_RG16I,					tcu::Sampler::MODE_LAST,	true	},
2555 			{ "uint_color",			GL_R8UI,					tcu::Sampler::MODE_LAST,	true	},
2556 			{ "unorm_depth",		GL_DEPTH_COMPONENT16,		tcu::Sampler::MODE_DEPTH,	false	},
2557 			{ "float_depth",		GL_DEPTH32F_STENCIL8,		tcu::Sampler::MODE_DEPTH,	false	},
2558 			{ "uint_stencil",		GL_DEPTH32F_STENCIL8,		tcu::Sampler::MODE_STENCIL,	false	},
2559 			{ "compressed_color",	GL_COMPRESSED_RGB8_ETC2,	tcu::Sampler::MODE_LAST,	false	},
2560 		};
2561 		static const struct
2562 		{
2563 			const char*	name;
2564 			deUint32	sWrap;
2565 			deUint32	tWrap;
2566 			deUint32	rWrap;
2567 			bool		is3D;
2568 		} wrapConfigs[] =
2569 		{
2570 			// 2d configs
2571 			{ "s_clamp_to_edge_t_clamp_to_border",						GL_CLAMP_TO_EDGE,	GL_CLAMP_TO_BORDER,	GL_NONE,			false	},
2572 			{ "s_repeat_t_clamp_to_border",								GL_REPEAT,			GL_CLAMP_TO_BORDER,	GL_NONE,			false	},
2573 			{ "s_mirrored_repeat_t_clamp_to_border",					GL_MIRRORED_REPEAT,	GL_CLAMP_TO_BORDER,	GL_NONE,			false	},
2574 
2575 			// 3d configs
2576 			{ "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	},
2577 			{ "s_clamp_to_border_t_clamp_to_border_r_repeat",			GL_CLAMP_TO_BORDER,	GL_CLAMP_TO_BORDER,	GL_REPEAT,			true	},
2578 			{ "s_mirrored_repeat_t_clamp_to_border_r_repeat",			GL_MIRRORED_REPEAT,	GL_CLAMP_TO_BORDER,	GL_REPEAT,			true	},
2579 			{ "s_repeat_t_mirrored_repeat_r_clamp_to_border",			GL_REPEAT,			GL_MIRRORED_REPEAT,	GL_CLAMP_TO_BORDER,	true	},
2580 		};
2581 
2582 		tcu::TestCaseGroup* const perAxisGroup = new tcu::TestCaseGroup(m_testCtx, "per_axis_wrap_mode", "Per-axis wrapping modes");
2583 		addChild(perAxisGroup);
2584 
2585 		// .texture_nd
2586 		for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2587 		{
2588 			tcu::TestCaseGroup* const targetGroup = new tcu::TestCaseGroup(m_testCtx, targets[targetNdx].name, "Texture target test");
2589 			perAxisGroup->addChild(targetGroup);
2590 
2591 			// .format
2592 			for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
2593 			{
2594 				if (targets[targetNdx].is3D && !formats[formatNdx].supports3D)
2595 					continue;
2596 				else
2597 				{
2598 					const deUint32							format			= formats[formatNdx].format;
2599 					const tcu::Sampler::DepthStencilMode	sampleMode		= formats[formatNdx].mode;
2600 					const bool								coreFilterable	= isCoreFilterableFormat(format, sampleMode);
2601 					tcu::TestCaseGroup* const				formatGroup		= new tcu::TestCaseGroup(m_testCtx, formats[formatNdx].name, "Format test");
2602 					targetGroup->addChild(formatGroup);
2603 
2604 					// .linear
2605 					// .nearest
2606 					// .gather
2607 					for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx)
2608 					{
2609 						const deUint32 filter = s_filters[filterNdx].filter;
2610 
2611 						if (!coreFilterable && filterRequiresFilterability(filter))
2612 						{
2613 							// skip linear on pure integers
2614 							continue;
2615 						}
2616 						else if (s_filters[filterNdx].sampling == TextureBorderClampTest::SAMPLE_GATHER && targets[targetNdx].is3D)
2617 						{
2618 							// skip gather on 3d
2619 							continue;
2620 						}
2621 						else
2622 						{
2623 							tcu::TestCaseGroup* const filteringGroup = new tcu::TestCaseGroup(m_testCtx, s_filters[filterNdx].name, "Tests with specific filter");
2624 							formatGroup->addChild(filteringGroup);
2625 
2626 							// .s_XXX_t_XXX(_r_XXX)
2627 							for (int wrapNdx = 0; wrapNdx < DE_LENGTH_OF_ARRAY(wrapConfigs); ++wrapNdx)
2628 							{
2629 								if (wrapConfigs[wrapNdx].is3D != targets[targetNdx].is3D)
2630 									continue;
2631 								else
2632 								{
2633 									for (int sizeNdx = 0; sizeNdx < 2; ++sizeNdx)
2634 									{
2635 										const char* const		wrapName			= wrapConfigs[wrapNdx].name;
2636 										const bool				isNpotCase			= (sizeNdx == 1);
2637 										const char* const		sizeNameExtension	= (isNpotCase) ? ("_npot") : ("_pot");
2638 										const SizeType			size				= (isNpotCase) ? (SIZE_NPOT) : (SIZE_POT);
2639 
2640 										if (!targets[targetNdx].is3D)
2641 											filteringGroup->addChild(new TextureBorderClampPerAxisCase2D(m_context,
2642 																										 (std::string() + wrapName + sizeNameExtension).c_str(),
2643 																										 "",
2644 																										 format,
2645 																										 sampleMode,
2646 																										 size,
2647 																										 filter,
2648 																										 wrapConfigs[wrapNdx].sWrap,
2649 																										 wrapConfigs[wrapNdx].tWrap,
2650 																										 s_filters[filterNdx].sampling));
2651 										else
2652 										{
2653 											DE_ASSERT(sampleMode == tcu::Sampler::MODE_LAST);
2654 											filteringGroup->addChild(new TextureBorderClampPerAxisCase3D(m_context,
2655 																										 (std::string() + wrapName + sizeNameExtension).c_str(),
2656 																										 "",
2657 																										 format,
2658 																										 size,
2659 																										 filter,
2660 																										 wrapConfigs[wrapNdx].sWrap,
2661 																										 wrapConfigs[wrapNdx].tWrap,
2662 																										 wrapConfigs[wrapNdx].rWrap));
2663 										}
2664 									}
2665 								}
2666 							}
2667 						}
2668 					}
2669 				}
2670 			}
2671 		}
2672 	}
2673 
2674 	// .depth_compare_mode
2675 	{
2676 		static const struct
2677 		{
2678 			const char*						name;
2679 			deUint32						format;
2680 		} formats[] =
2681 		{
2682 			{ "depth_component16",		GL_DEPTH_COMPONENT16	},
2683 			{ "depth_component24",		GL_DEPTH_COMPONENT24	},
2684 			{ "depth24_stencil8",		GL_DEPTH24_STENCIL8		},
2685 			{ "depth32f_stencil8",		GL_DEPTH32F_STENCIL8	},
2686 		};
2687 
2688 		tcu::TestCaseGroup* const compareGroup = new tcu::TestCaseGroup(m_testCtx, "depth_compare_mode", "Tests depth compare mode");
2689 		addChild(compareGroup);
2690 
2691 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
2692 		{
2693 			const deUint32							format			= formats[formatNdx].format;
2694 			tcu::TestCaseGroup* const				formatGroup		= new tcu::TestCaseGroup(m_testCtx, formats[formatNdx].name, "Format test");
2695 
2696 			compareGroup->addChild(formatGroup);
2697 
2698 			// (format).(linear|nearest|gather)_(pot|npot)
2699 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx)
2700 			for (int sizeNdx = 0; sizeNdx < 2; ++sizeNdx)
2701 			{
2702 					const bool				isNpotCase		= (sizeNdx == 1);
2703 					const char* const		sizeName		= (isNpotCase) ? ("size_npot") : ("size_pot");
2704 					const SizeType			sizeType		= (isNpotCase) ? (SIZE_NPOT) : (SIZE_POT);
2705 					const std::string		caseName		= std::string() + s_filters[filterNdx].name + "_" + sizeName;
2706 					const deUint32			filter			= s_filters[filterNdx].filter;
2707 
2708 					formatGroup->addChild(new TextureBorderClampDepthCompareCase(m_context,
2709 																				 caseName.c_str(),
2710 																				 "",
2711 																				 format,
2712 																				 sizeType,
2713 																				 filter,
2714 																				 s_filters[filterNdx].sampling));
2715 			}
2716 		}
2717 	}
2718 
2719 	// unused channels (A in rgb, G in stencil etc.)
2720 	{
2721 		static const struct
2722 		{
2723 			const char*						name;
2724 			deUint32						format;
2725 			tcu::Sampler::DepthStencilMode	mode;
2726 		} formats[] =
2727 		{
2728 			{ "r8",										GL_R8,						tcu::Sampler::MODE_LAST		},
2729 			{ "rg8_snorm",								GL_RG8_SNORM,				tcu::Sampler::MODE_LAST		},
2730 			{ "rgb8",									GL_RGB8,					tcu::Sampler::MODE_LAST		},
2731 			{ "rg32f",									GL_RG32F,					tcu::Sampler::MODE_LAST		},
2732 			{ "r16i",									GL_RG16I,					tcu::Sampler::MODE_LAST		},
2733 			{ "luminance",								GL_LUMINANCE,				tcu::Sampler::MODE_LAST		},
2734 			{ "alpha",									GL_ALPHA,					tcu::Sampler::MODE_LAST		},
2735 			{ "luminance_alpha",						GL_LUMINANCE_ALPHA,			tcu::Sampler::MODE_LAST		},
2736 			{ "depth_component16",						GL_DEPTH_COMPONENT16,		tcu::Sampler::MODE_DEPTH	},
2737 			{ "depth_component32f",						GL_DEPTH_COMPONENT32F,		tcu::Sampler::MODE_DEPTH	},
2738 			{ "stencil_index8",							GL_STENCIL_INDEX8,			tcu::Sampler::MODE_STENCIL	},
2739 			{ "depth32f_stencil8_sample_depth",			GL_DEPTH32F_STENCIL8,		tcu::Sampler::MODE_DEPTH	},
2740 			{ "depth32f_stencil8_sample_stencil",		GL_DEPTH32F_STENCIL8,		tcu::Sampler::MODE_STENCIL	},
2741 			{ "depth24_stencil8_sample_depth",			GL_DEPTH24_STENCIL8,		tcu::Sampler::MODE_DEPTH	},
2742 			{ "depth24_stencil8_sample_stencil",		GL_DEPTH24_STENCIL8,		tcu::Sampler::MODE_STENCIL	},
2743 			{ "compressed_r11_eac",						GL_COMPRESSED_R11_EAC,		tcu::Sampler::MODE_LAST		},
2744 		};
2745 
2746 		tcu::TestCaseGroup* const unusedGroup = new tcu::TestCaseGroup(m_testCtx, "unused_channels", "Tests channels that are not present in the internal format");
2747 		addChild(unusedGroup);
2748 
2749 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
2750 		{
2751 			if (isFormatSupported(formats[formatNdx].format, m_isGL45))
2752 			{
2753 				unusedGroup->addChild(new TextureBorderClampUnusedChannelCase(m_context,
2754 																			  formats[formatNdx].name,
2755 																			  "",
2756 																			  formats[formatNdx].format,
2757 																			  formats[formatNdx].mode));
2758 			}
2759 		}
2760 	}
2761 }
2762 
2763 } // Functional
2764 } // gles31
2765 } // deqp
2766