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