/*-------------------------------------------------------------------------
 * drawElements Quality Program Tester Core
 * ----------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Texture compare (shadow) result verifier.
 *//*--------------------------------------------------------------------*/

#include "tcuTexCompareVerifier.hpp"
#include "tcuTexVerifierUtil.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuVectorUtil.hpp"
#include "deMath.h"

namespace tcu
{

using namespace TexVerifierUtil;

// Generic utilities

#if defined(DE_DEBUG)
static bool isSamplerSupported (const Sampler& sampler)
{
	return sampler.compare != Sampler::COMPAREMODE_NONE &&
		   isWrapModeSupported(sampler.wrapS)			&&
		   isWrapModeSupported(sampler.wrapT)			&&
		   isWrapModeSupported(sampler.wrapR);
}
#endif // DE_DEBUG

struct CmpResultSet
{
	bool	isTrue;
	bool	isFalse;

	CmpResultSet (void)
		: isTrue	(false)
		, isFalse	(false)
	{
	}
};

static CmpResultSet execCompare (const Sampler::CompareMode	compareMode,
								 const float				cmpValue_,
								 const float				cmpReference_,
								 const int					referenceBits,
								 const bool					isFixedPoint)
{
	const bool		clampValues		= isFixedPoint;	// if comparing against a floating point texture, ref (and value) is not clamped
	const float		cmpValue		= (clampValues) ? (de::clamp(cmpValue_, 0.0f, 1.0f)) : (cmpValue_);
	const float		cmpReference	= (clampValues) ? (de::clamp(cmpReference_, 0.0f, 1.0f)) : (cmpReference_);
	const float		err				= computeFixedPointError(referenceBits);
	CmpResultSet	res;

	switch (compareMode)
	{
		case Sampler::COMPAREMODE_LESS:
			res.isTrue	= cmpReference-err < cmpValue;
			res.isFalse	= cmpReference+err >= cmpValue;
			break;

		case Sampler::COMPAREMODE_LESS_OR_EQUAL:
			res.isTrue	= cmpReference-err <= cmpValue;
			res.isFalse	= cmpReference+err > cmpValue;
			break;

		case Sampler::COMPAREMODE_GREATER:
			res.isTrue	= cmpReference+err > cmpValue;
			res.isFalse	= cmpReference-err <= cmpValue;
			break;

		case Sampler::COMPAREMODE_GREATER_OR_EQUAL:
			res.isTrue	= cmpReference+err >= cmpValue;
			res.isFalse	= cmpReference-err < cmpValue;
			break;

		case Sampler::COMPAREMODE_EQUAL:
			res.isTrue	= de::inRange(cmpValue, cmpReference-err, cmpReference+err);
			res.isFalse	= err != 0.0f || cmpValue != cmpReference;
			break;

		case Sampler::COMPAREMODE_NOT_EQUAL:
			res.isTrue	= err != 0.0f || cmpValue != cmpReference;
			res.isFalse	= de::inRange(cmpValue, cmpReference-err, cmpReference+err);
			break;

		case Sampler::COMPAREMODE_ALWAYS:
			res.isTrue	= true;
			break;

		case Sampler::COMPAREMODE_NEVER:
			res.isFalse	= true;
			break;

		default:
			DE_ASSERT(false);
	}

	DE_ASSERT(res.isTrue || res.isFalse);
	return res;
}

static inline bool isResultInSet (const CmpResultSet resultSet, const float result, const int resultBits)
{
	const float err		= computeFixedPointError(resultBits);
	const float	minR	= result-err;
	const float	maxR	= result+err;

	return (resultSet.isTrue	&& de::inRange(1.0f, minR, maxR)) ||
		   (resultSet.isFalse	&& de::inRange(0.0f, minR, maxR));
}

static inline bool coordsInBounds (const ConstPixelBufferAccess& access, int x, int y, int z)
{
	return de::inBounds(x, 0, access.getWidth()) && de::inBounds(y, 0, access.getHeight()) && de::inBounds(z, 0, access.getDepth());
}

static float lookupDepth (const tcu::ConstPixelBufferAccess& access, const Sampler& sampler, int i, int j, int k)
{
	if (coordsInBounds(access, i, j, k))
		return access.getPixDepth(i, j, k);
	else
		return sampleTextureBorder<float>(access.getFormat(), sampler).x();
}

// lookup depth value at a point that is guaranteed to not sample border such as cube map faces.
static float lookupDepthNoBorder (const tcu::ConstPixelBufferAccess& access, const Sampler& sampler, int i, int j, int k = 0)
{
	DE_UNREF(sampler);
	DE_ASSERT(coordsInBounds(access, i, j, k));
	return access.getPixDepth(i, j, k);
}

// Values are in order (0,0), (1,0), (0,1), (1,1)
static float bilinearInterpolate (const Vec4& values, const float x, const float y)
{
	const float		v00		= values[0];
	const float		v10		= values[1];
	const float		v01		= values[2];
	const float		v11		= values[3];
	const float		res		= v00*(1.0f-x)*(1.0f-y) + v10*x*(1.0f-y) + v01*(1.0f-x)*y + v11*x*y;
	return res;
}

static bool isFixedPointDepthTextureFormat (const tcu::TextureFormat& format)
{
	const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);

	if (format.order == TextureFormat::D)
	{
		// depth internal formats cannot be non-normalized integers
		return channelClass != tcu::TEXTURECHANNELCLASS_FLOATING_POINT;
	}
	else if (format.order == TextureFormat::DS)
	{
		// combined formats have no single channel class, detect format manually
		switch (format.type)
		{
			case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:	return false;
			case tcu::TextureFormat::UNSIGNED_INT_16_8_8:			return true;
			case tcu::TextureFormat::UNSIGNED_INT_24_8:				return true;
			case tcu::TextureFormat::UNSIGNED_INT_24_8_REV:			return true;

			default:
			{
				// unknown format
				DE_ASSERT(false);
				return true;
			}
		}
	}

	return false;
}

static bool isLinearCompareValid (const Sampler::CompareMode	compareMode,
								  const TexComparePrecision&	prec,
								  const Vec2&					depths,
								  const Vec2&					fBounds,
								  const float					cmpReference,
								  const float					result,
								  const bool					isFixedPointDepth)
{
	DE_ASSERT(0.0f <= fBounds.x() && fBounds.x() <= fBounds.y() && fBounds.y() <= 1.0f);

	const float			d0			= depths[0];
	const float			d1			= depths[1];

	const CmpResultSet	cmp0		= execCompare(compareMode, d0, cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp1		= execCompare(compareMode, d1, cmpReference, prec.referenceBits, isFixedPointDepth);

	const deUint32		isTrue		= (deUint32(cmp0.isTrue)<<0)
									| (deUint32(cmp1.isTrue)<<1);
	const deUint32		isFalse		= (deUint32(cmp0.isFalse)<<0)
									| (deUint32(cmp1.isFalse)<<1);

	// Interpolation parameters
	const float			f0			= fBounds.x();
	const float			f1			= fBounds.y();

	// Error parameters
	const float			pcfErr		= computeFixedPointError(prec.pcfBits);
	const float			resErr		= computeFixedPointError(prec.resultBits);
	const float			totalErr	= pcfErr+resErr;

	// Iterate over all valid combinations.
	for (deUint32 comb = 0; comb < (1<<2); comb++)
	{
		// Filter out invalid combinations.
		if (((comb & isTrue) | (~comb & isFalse)) != (1<<2)-1)
			continue;

		const bool		cmp0True	= ((comb>>0)&1) != 0;
		const bool		cmp1True	= ((comb>>1)&1) != 0;

		const float		ref0		= cmp0True ? 1.0f : 0.0f;
		const float		ref1		= cmp1True ? 1.0f : 0.0f;

		const float		v0			= ref0*(1.0f-f0) + ref1*f0;
		const float		v1			= ref0*(1.0f-f1) + ref1*f1;
		const float		minV		= de::min(v0, v1);
		const float		maxV		= de::max(v0, v1);
		const float		minR		= minV-totalErr;
		const float		maxR		= maxV+totalErr;

		if (de::inRange(result, minR, maxR))
			return true;
	}

	return false;
}

static inline BVec4 extractBVec4 (const deUint32 val, int offset)
{
	return BVec4(((val>>(offset+0))&1) != 0,
				 ((val>>(offset+1))&1) != 0,
				 ((val>>(offset+2))&1) != 0,
				 ((val>>(offset+3))&1) != 0);
}

static bool isBilinearAnyCompareValid (const Sampler::CompareMode	compareMode,
									   const TexComparePrecision&	prec,
									   const Vec4&					depths,
									   const float					cmpReference,
									   const float					result,
									   const bool					isFixedPointDepth)
{
	DE_ASSERT(prec.pcfBits == 0);

	const float			d0			= depths[0];
	const float			d1			= depths[1];
	const float			d2			= depths[2];
	const float			d3			= depths[3];

	const CmpResultSet	cmp0		= execCompare(compareMode, d0, cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp1		= execCompare(compareMode, d1, cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp2		= execCompare(compareMode, d2, cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp3		= execCompare(compareMode, d3, cmpReference, prec.referenceBits, isFixedPointDepth);

	const bool			canBeTrue	= cmp0.isTrue || cmp1.isTrue || cmp2.isTrue || cmp3.isTrue;
	const bool			canBeFalse	= cmp0.isFalse || cmp1.isFalse || cmp2.isFalse || cmp3.isFalse;

	const float			resErr		= computeFixedPointError(prec.resultBits);

	const float			minBound	= canBeFalse ? 0.0f : 1.0f;
	const float			maxBound	= canBeTrue ? 1.0f : 0.0f;

	return de::inRange(result, minBound-resErr, maxBound+resErr);
}

static bool isBilinearPCFCompareValid (const Sampler::CompareMode	compareMode,
									   const TexComparePrecision&	prec,
									   const Vec4&					depths,
									   const Vec2&					xBounds,
									   const Vec2&					yBounds,
									   const float					cmpReference,
									   const float					result,
									   const bool					isFixedPointDepth)
{
	DE_ASSERT(0.0f <= xBounds.x() && xBounds.x() <= xBounds.y() && xBounds.y() <= 1.0f);
	DE_ASSERT(0.0f <= yBounds.x() && yBounds.x() <= yBounds.y() && yBounds.y() <= 1.0f);
	DE_ASSERT(prec.pcfBits > 0);

	const float			d0			= depths[0];
	const float			d1			= depths[1];
	const float			d2			= depths[2];
	const float			d3			= depths[3];

	const CmpResultSet	cmp0		= execCompare(compareMode, d0, cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp1		= execCompare(compareMode, d1, cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp2		= execCompare(compareMode, d2, cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp3		= execCompare(compareMode, d3, cmpReference, prec.referenceBits, isFixedPointDepth);

	const deUint32		isTrue		= (deUint32(cmp0.isTrue)<<0)
									| (deUint32(cmp1.isTrue)<<1)
									| (deUint32(cmp2.isTrue)<<2)
									| (deUint32(cmp3.isTrue)<<3);
	const deUint32		isFalse		= (deUint32(cmp0.isFalse)<<0)
									| (deUint32(cmp1.isFalse)<<1)
									| (deUint32(cmp2.isFalse)<<2)
									| (deUint32(cmp3.isFalse)<<3);

	// Interpolation parameters
	const float			x0			= xBounds.x();
	const float			x1			= xBounds.y();
	const float			y0			= yBounds.x();
	const float			y1			= yBounds.y();

	// Error parameters
	const float			pcfErr		= computeFixedPointError(prec.pcfBits);
	const float			resErr		= computeFixedPointError(prec.resultBits);
	const float			totalErr	= pcfErr+resErr;

	// Iterate over all valid combinations.
	// \note It is not enough to compute minmax over all possible result sets, as ranges may
	//		 not necessarily overlap, i.e. there are gaps between valid ranges.
	for (deUint32 comb = 0; comb < (1<<4); comb++)
	{
		// Filter out invalid combinations:
		//  1) True bit is set in comb but not in isTrue => sample can not be true
		//  2) True bit is NOT set in comb and not in isFalse => sample can not be false
		if (((comb & isTrue) | (~comb & isFalse)) != (1<<4)-1)
			continue;

		const BVec4		cmpTrue		= extractBVec4(comb, 0);
		const Vec4		refVal		= select(Vec4(1.0f), Vec4(0.0f), cmpTrue);

		const float		v0			= bilinearInterpolate(refVal, x0, y0);
		const float		v1			= bilinearInterpolate(refVal, x1, y0);
		const float		v2			= bilinearInterpolate(refVal, x0, y1);
		const float		v3			= bilinearInterpolate(refVal, x1, y1);
		const float		minV		= de::min(v0, de::min(v1, de::min(v2, v3)));
		const float		maxV		= de::max(v0, de::max(v1, de::max(v2, v3)));
		const float		minR		= minV-totalErr;
		const float		maxR		= maxV+totalErr;

		if (de::inRange(result, minR, maxR))
			return true;
	}

	return false;
}

static bool isBilinearCompareValid (const Sampler::CompareMode	compareMode,
									const TexComparePrecision&	prec,
									const Vec4&					depths,
									const Vec2&					xBounds,
									const Vec2&					yBounds,
									const float					cmpReference,
									const float					result,
									const bool					isFixedPointDepth)
{
	if (prec.pcfBits > 0)
		return isBilinearPCFCompareValid(compareMode, prec, depths, xBounds, yBounds, cmpReference, result, isFixedPointDepth);
	else
		return isBilinearAnyCompareValid(compareMode, prec, depths, cmpReference, result, isFixedPointDepth);
}

static bool isTrilinearAnyCompareValid (const Sampler::CompareMode	compareMode,
										const TexComparePrecision&	prec,
										const Vec4&					depths0,
										const Vec4&					depths1,
										const float					cmpReference,
										const float					result,
										const bool					isFixedPointDepth)
{
	DE_ASSERT(prec.pcfBits == 0);

	const CmpResultSet	cmp00		= execCompare(compareMode, depths0[0], cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp01		= execCompare(compareMode, depths0[1], cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp02		= execCompare(compareMode, depths0[2], cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp03		= execCompare(compareMode, depths0[3], cmpReference, prec.referenceBits, isFixedPointDepth);

	const CmpResultSet	cmp10		= execCompare(compareMode, depths1[0], cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp11		= execCompare(compareMode, depths1[1], cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp12		= execCompare(compareMode, depths1[2], cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp13		= execCompare(compareMode, depths1[3], cmpReference, prec.referenceBits, isFixedPointDepth);

	const bool			canBeTrue	= cmp00.isTrue ||
									  cmp01.isTrue ||
									  cmp02.isTrue ||
									  cmp03.isTrue ||
									  cmp10.isTrue ||
									  cmp11.isTrue ||
									  cmp12.isTrue ||
									  cmp13.isTrue;
	const bool			canBeFalse	= cmp00.isFalse ||
									  cmp01.isFalse ||
									  cmp02.isFalse ||
									  cmp03.isFalse ||
									  cmp10.isFalse ||
									  cmp11.isFalse ||
									  cmp12.isFalse ||
									  cmp13.isFalse;

	const float			resErr		= computeFixedPointError(prec.resultBits);

	const float			minBound	= canBeFalse ? 0.0f : 1.0f;
	const float			maxBound	= canBeTrue ? 1.0f : 0.0f;

	return de::inRange(result, minBound-resErr, maxBound+resErr);
}

static bool isTrilinearPCFCompareValid (const Sampler::CompareMode	compareMode,
										const TexComparePrecision&	prec,
										const Vec4&					depths0,
										const Vec4&					depths1,
										const Vec2&					xBounds0,
										const Vec2&					yBounds0,
										const Vec2&					xBounds1,
										const Vec2&					yBounds1,
										const Vec2&					fBounds,
										const float					cmpReference,
										const float					result,
										const bool					isFixedPointDepth)
{
	DE_ASSERT(0.0f <= xBounds0.x() && xBounds0.x() <= xBounds0.y() && xBounds0.y() <= 1.0f);
	DE_ASSERT(0.0f <= yBounds0.x() && yBounds0.x() <= yBounds0.y() && yBounds0.y() <= 1.0f);
	DE_ASSERT(0.0f <= xBounds1.x() && xBounds1.x() <= xBounds1.y() && xBounds1.y() <= 1.0f);
	DE_ASSERT(0.0f <= yBounds1.x() && yBounds1.x() <= yBounds1.y() && yBounds1.y() <= 1.0f);
	DE_ASSERT(0.0f <= fBounds.x() && fBounds.x() <= fBounds.y() && fBounds.y() <= 1.0f);
	DE_ASSERT(prec.pcfBits > 0);

	const CmpResultSet	cmp00		= execCompare(compareMode, depths0[0], cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp01		= execCompare(compareMode, depths0[1], cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp02		= execCompare(compareMode, depths0[2], cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp03		= execCompare(compareMode, depths0[3], cmpReference, prec.referenceBits, isFixedPointDepth);

	const CmpResultSet	cmp10		= execCompare(compareMode, depths1[0], cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp11		= execCompare(compareMode, depths1[1], cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp12		= execCompare(compareMode, depths1[2], cmpReference, prec.referenceBits, isFixedPointDepth);
	const CmpResultSet	cmp13		= execCompare(compareMode, depths1[3], cmpReference, prec.referenceBits, isFixedPointDepth);

	const deUint32		isTrue		= (deUint32(cmp00.isTrue)<<0)
									| (deUint32(cmp01.isTrue)<<1)
									| (deUint32(cmp02.isTrue)<<2)
									| (deUint32(cmp03.isTrue)<<3)
									| (deUint32(cmp10.isTrue)<<4)
									| (deUint32(cmp11.isTrue)<<5)
									| (deUint32(cmp12.isTrue)<<6)
									| (deUint32(cmp13.isTrue)<<7);
	const deUint32		isFalse		= (deUint32(cmp00.isFalse)<<0)
									| (deUint32(cmp01.isFalse)<<1)
									| (deUint32(cmp02.isFalse)<<2)
									| (deUint32(cmp03.isFalse)<<3)
									| (deUint32(cmp10.isFalse)<<4)
									| (deUint32(cmp11.isFalse)<<5)
									| (deUint32(cmp12.isFalse)<<6)
									| (deUint32(cmp13.isFalse)<<7);

	// Error parameters
	const float			pcfErr		= computeFixedPointError(prec.pcfBits);
	const float			resErr		= computeFixedPointError(prec.resultBits);
	const float			totalErr	= pcfErr+resErr;

	// Iterate over all valid combinations.
	for (deUint32 comb = 0; comb < (1<<8); comb++)
	{
		// Filter out invalid combinations.
		if (((comb & isTrue) | (~comb & isFalse)) != (1<<8)-1)
			continue;

		const BVec4		cmpTrue0	= extractBVec4(comb, 0);
		const BVec4		cmpTrue1	= extractBVec4(comb, 4);
		const Vec4		refVal0		= select(Vec4(1.0f), Vec4(0.0f), cmpTrue0);
		const Vec4		refVal1		= select(Vec4(1.0f), Vec4(0.0f), cmpTrue1);

		// Bilinear interpolation within levels.
		const float		v00			= bilinearInterpolate(refVal0, xBounds0.x(), yBounds0.x());
		const float		v01			= bilinearInterpolate(refVal0, xBounds0.y(), yBounds0.x());
		const float		v02			= bilinearInterpolate(refVal0, xBounds0.x(), yBounds0.y());
		const float		v03			= bilinearInterpolate(refVal0, xBounds0.y(), yBounds0.y());
		const float		minV0		= de::min(v00, de::min(v01, de::min(v02, v03)));
		const float		maxV0		= de::max(v00, de::max(v01, de::max(v02, v03)));

		const float		v10			= bilinearInterpolate(refVal1, xBounds1.x(), yBounds1.x());
		const float		v11			= bilinearInterpolate(refVal1, xBounds1.y(), yBounds1.x());
		const float		v12			= bilinearInterpolate(refVal1, xBounds1.x(), yBounds1.y());
		const float		v13			= bilinearInterpolate(refVal1, xBounds1.y(), yBounds1.y());
		const float		minV1		= de::min(v10, de::min(v11, de::min(v12, v13)));
		const float		maxV1		= de::max(v10, de::max(v11, de::max(v12, v13)));

		// Compute min-max bounds by filtering between minimum bounds and maximum bounds between levels.
		// HW can end up choosing pretty much any of samples between levels, and thus interpolating
		// between minimums should yield lower bound for range, and same for upper bound.
		// \todo [2013-07-17 pyry] This seems separable? Can this be optimized? At least ranges could be pre-computed and later combined.
		const float		minF0		= minV0*(1.0f-fBounds.x()) + minV1*fBounds.x();
		const float		minF1		= minV0*(1.0f-fBounds.y()) + minV1*fBounds.y();
		const float		maxF0		= maxV0*(1.0f-fBounds.x()) + maxV1*fBounds.x();
		const float		maxF1		= maxV0*(1.0f-fBounds.y()) + maxV1*fBounds.y();

		const float		minF		= de::min(minF0, minF1);
		const float		maxF		= de::max(maxF0, maxF1);

		const float		minR		= minF-totalErr;
		const float		maxR		= maxF+totalErr;

		if (de::inRange(result, minR, maxR))
			return true;
	}

	return false;
}

static bool isTrilinearCompareValid (const Sampler::CompareMode	compareMode,
									 const TexComparePrecision&	prec,
									 const Vec4&				depths0,
									 const Vec4&				depths1,
									 const Vec2&				xBounds0,
									 const Vec2&				yBounds0,
									 const Vec2&				xBounds1,
									 const Vec2&				yBounds1,
									 const Vec2&				fBounds,
									 const float				cmpReference,
									 const float				result,
									 const bool					isFixedPointDepth)
{
	if (prec.pcfBits > 0)
		return isTrilinearPCFCompareValid(compareMode, prec, depths0, depths1, xBounds0, yBounds0, xBounds1, yBounds1, fBounds, cmpReference, result, isFixedPointDepth);
	else
		return isTrilinearAnyCompareValid(compareMode, prec, depths0, depths1, cmpReference, result, isFixedPointDepth);
}

static bool isNearestCompareResultValid (const ConstPixelBufferAccess&		level,
										 const Sampler&						sampler,
										 const TexComparePrecision&			prec,
										 const Vec2&						coord,
										 const int							coordZ,
										 const float						cmpReference,
										 const float						result)
{
	const bool	isFixedPointDepth	= isFixedPointDepthTextureFormat(level.getFormat());
	const Vec2	uBounds				= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(),	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2	vBounds				= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(),	coord.y(), prec.coordBits.y(), prec.uvwBits.y());

	// Integer coordinates - without wrap mode
	const int	minI		= deFloorFloatToInt32(uBounds.x());
	const int	maxI		= deFloorFloatToInt32(uBounds.y());
	const int	minJ		= deFloorFloatToInt32(vBounds.x());
	const int	maxJ		= deFloorFloatToInt32(vBounds.y());

	for (int j = minJ; j <= maxJ; j++)
	{
		for (int i = minI; i <= maxI; i++)
		{
			const int			x		= wrap(sampler.wrapS, i, level.getWidth());
			const int			y		= wrap(sampler.wrapT, j, level.getHeight());
			const float			depth	= lookupDepth(level, sampler, x, y, coordZ);
			const CmpResultSet	resSet	= execCompare(sampler.compare, depth, cmpReference, prec.referenceBits, isFixedPointDepth);

			if (isResultInSet(resSet, result, prec.resultBits))
				return true;
		}
	}

	return false;
}

static bool isLinearCompareResultValid (const ConstPixelBufferAccess&		level,
										const Sampler&						sampler,
										const TexComparePrecision&			prec,
										const Vec2&							coord,
										const int							coordZ,
										const float							cmpReference,
										const float							result)
{
	const bool	isFixedPointDepth	= isFixedPointDepthTextureFormat(level.getFormat());
	const Vec2	uBounds				= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getWidth(),	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2	vBounds				= computeNonNormalizedCoordBounds(sampler.normalizedCoords, level.getHeight(),	coord.y(), prec.coordBits.y(), prec.uvwBits.y());

	// Integer coordinate bounds for (x0,y0) - without wrap mode
	const int	minI		= deFloorFloatToInt32(uBounds.x()-0.5f);
	const int	maxI		= deFloorFloatToInt32(uBounds.y()-0.5f);
	const int	minJ		= deFloorFloatToInt32(vBounds.x()-0.5f);
	const int	maxJ		= deFloorFloatToInt32(vBounds.y()-0.5f);

	const int	w			= level.getWidth();
	const int	h			= level.getHeight();

	// \todo [2013-07-03 pyry] This could be optimized by first computing ranges based on wrap mode.

	for (int j = minJ; j <= maxJ; j++)
	{
		for (int i = minI; i <= maxI; i++)
		{
			// Wrapped coordinates
			const int	x0		= wrap(sampler.wrapS, i  , w);
			const int	x1		= wrap(sampler.wrapS, i+1, w);
			const int	y0		= wrap(sampler.wrapT, j  , h);
			const int	y1		= wrap(sampler.wrapT, j+1, h);

			// Bounds for filtering factors
			const float	minA	= de::clamp((uBounds.x()-0.5f)-float(i), 0.0f, 1.0f);
			const float	maxA	= de::clamp((uBounds.y()-0.5f)-float(i), 0.0f, 1.0f);
			const float	minB	= de::clamp((vBounds.x()-0.5f)-float(j), 0.0f, 1.0f);
			const float	maxB	= de::clamp((vBounds.y()-0.5f)-float(j), 0.0f, 1.0f);

			const Vec4	depths	(lookupDepth(level, sampler, x0, y0, coordZ),
								 lookupDepth(level, sampler, x1, y0, coordZ),
								 lookupDepth(level, sampler, x0, y1, coordZ),
								 lookupDepth(level, sampler, x1, y1, coordZ));

			if (isBilinearCompareValid(sampler.compare, prec, depths, Vec2(minA, maxA), Vec2(minB, maxB), cmpReference, result, isFixedPointDepth))
				return true;
		}
	}

	return false;
}

static bool isLevelCompareResultValid (const ConstPixelBufferAccess&	level,
									   const Sampler&					sampler,
									   const Sampler::FilterMode		filterMode,
									   const TexComparePrecision&		prec,
									   const Vec2&						coord,
									   const int						coordZ,
									   const float						cmpReference,
									   const float						result)
{
	if (filterMode == Sampler::LINEAR)
		return isLinearCompareResultValid(level, sampler, prec, coord, coordZ, cmpReference, result);
	else
		return isNearestCompareResultValid(level, sampler, prec, coord, coordZ, cmpReference, result);
}

static bool isNearestMipmapLinearCompareResultValid (const ConstPixelBufferAccess&	level0,
													 const ConstPixelBufferAccess&	level1,
													 const Sampler&					sampler,
													 const TexComparePrecision&		prec,
													 const Vec2&					coord,
													 const int						coordZ,
													 const Vec2&					fBounds,
													 const float					cmpReference,
													 const float					result)
{
	const bool	isFixedPointDepth	= isFixedPointDepthTextureFormat(level0.getFormat());

	const int	w0					= level0.getWidth();
	const int	w1					= level1.getWidth();
	const int	h0					= level0.getHeight();
	const int	h1					= level1.getHeight();

	const Vec2	uBounds0			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0,	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2	uBounds1			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1,	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2	vBounds0			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0,	coord.y(), prec.coordBits.y(), prec.uvwBits.y());
	const Vec2	vBounds1			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1,	coord.y(), prec.coordBits.y(), prec.uvwBits.y());

	// Integer coordinates - without wrap mode
	const int	minI0				= deFloorFloatToInt32(uBounds0.x());
	const int	maxI0				= deFloorFloatToInt32(uBounds0.y());
	const int	minI1				= deFloorFloatToInt32(uBounds1.x());
	const int	maxI1				= deFloorFloatToInt32(uBounds1.y());
	const int	minJ0				= deFloorFloatToInt32(vBounds0.x());
	const int	maxJ0				= deFloorFloatToInt32(vBounds0.y());
	const int	minJ1				= deFloorFloatToInt32(vBounds1.x());
	const int	maxJ1				= deFloorFloatToInt32(vBounds1.y());

	for (int j0 = minJ0; j0 <= maxJ0; j0++)
	{
		for (int i0 = minI0; i0 <= maxI0; i0++)
		{
			const float	depth0	= lookupDepth(level0, sampler, wrap(sampler.wrapS, i0, w0), wrap(sampler.wrapT, j0, h0), coordZ);

			for (int j1 = minJ1; j1 <= maxJ1; j1++)
			{
				for (int i1 = minI1; i1 <= maxI1; i1++)
				{
					const float	depth1	= lookupDepth(level1, sampler, wrap(sampler.wrapS, i1, w1), wrap(sampler.wrapT, j1, h1), coordZ);

					if (isLinearCompareValid(sampler.compare, prec, Vec2(depth0, depth1), fBounds, cmpReference, result, isFixedPointDepth))
						return true;
				}
			}
		}
	}

	return false;
}

static bool isLinearMipmapLinearCompareResultValid (const ConstPixelBufferAccess&	level0,
													const ConstPixelBufferAccess&	level1,
													const Sampler&					sampler,
													const TexComparePrecision&		prec,
													const Vec2&						coord,
													const int						coordZ,
													const Vec2&						fBounds,
													const float						cmpReference,
													const float						result)
{
	const bool	isFixedPointDepth	= isFixedPointDepthTextureFormat(level0.getFormat());

	// \todo [2013-07-04 pyry] This is strictly not correct as coordinates between levels should be dependent.
	//						   Right now this allows pairing any two valid bilinear quads.

	const int	w0					= level0.getWidth();
	const int	w1					= level1.getWidth();
	const int	h0					= level0.getHeight();
	const int	h1					= level1.getHeight();

	const Vec2	uBounds0			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, w0,	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2	uBounds1			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, w1,	coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2	vBounds0			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, h0,	coord.y(), prec.coordBits.y(), prec.uvwBits.y());
	const Vec2	vBounds1			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, h1,	coord.y(), prec.coordBits.y(), prec.uvwBits.y());

	// Integer coordinates - without wrap mode
	const int	minI0				= deFloorFloatToInt32(uBounds0.x()-0.5f);
	const int	maxI0				= deFloorFloatToInt32(uBounds0.y()-0.5f);
	const int	minI1				= deFloorFloatToInt32(uBounds1.x()-0.5f);
	const int	maxI1				= deFloorFloatToInt32(uBounds1.y()-0.5f);
	const int	minJ0				= deFloorFloatToInt32(vBounds0.x()-0.5f);
	const int	maxJ0				= deFloorFloatToInt32(vBounds0.y()-0.5f);
	const int	minJ1				= deFloorFloatToInt32(vBounds1.x()-0.5f);
	const int	maxJ1				= deFloorFloatToInt32(vBounds1.y()-0.5f);

	for (int j0 = minJ0; j0 <= maxJ0; j0++)
	{
		for (int i0 = minI0; i0 <= maxI0; i0++)
		{
			const float	minA0	= de::clamp((uBounds0.x()-0.5f)-float(i0), 0.0f, 1.0f);
			const float	maxA0	= de::clamp((uBounds0.y()-0.5f)-float(i0), 0.0f, 1.0f);
			const float	minB0	= de::clamp((vBounds0.x()-0.5f)-float(j0), 0.0f, 1.0f);
			const float	maxB0	= de::clamp((vBounds0.y()-0.5f)-float(j0), 0.0f, 1.0f);
			Vec4		depths0;

			{
				const int	x0		= wrap(sampler.wrapS, i0  , w0);
				const int	x1		= wrap(sampler.wrapS, i0+1, w0);
				const int	y0		= wrap(sampler.wrapT, j0  , h0);
				const int	y1		= wrap(sampler.wrapT, j0+1, h0);

				depths0[0] = lookupDepth(level0, sampler, x0, y0, coordZ);
				depths0[1] = lookupDepth(level0, sampler, x1, y0, coordZ);
				depths0[2] = lookupDepth(level0, sampler, x0, y1, coordZ);
				depths0[3] = lookupDepth(level0, sampler, x1, y1, coordZ);
			}

			for (int j1 = minJ1; j1 <= maxJ1; j1++)
			{
				for (int i1 = minI1; i1 <= maxI1; i1++)
				{
					const float	minA1	= de::clamp((uBounds1.x()-0.5f)-float(i1), 0.0f, 1.0f);
					const float	maxA1	= de::clamp((uBounds1.y()-0.5f)-float(i1), 0.0f, 1.0f);
					const float	minB1	= de::clamp((vBounds1.x()-0.5f)-float(j1), 0.0f, 1.0f);
					const float	maxB1	= de::clamp((vBounds1.y()-0.5f)-float(j1), 0.0f, 1.0f);
					Vec4		depths1;

					{
						const int	x0		= wrap(sampler.wrapS, i1  , w1);
						const int	x1		= wrap(sampler.wrapS, i1+1, w1);
						const int	y0		= wrap(sampler.wrapT, j1  , h1);
						const int	y1		= wrap(sampler.wrapT, j1+1, h1);

						depths1[0] = lookupDepth(level1, sampler, x0, y0, coordZ);
						depths1[1] = lookupDepth(level1, sampler, x1, y0, coordZ);
						depths1[2] = lookupDepth(level1, sampler, x0, y1, coordZ);
						depths1[3] = lookupDepth(level1, sampler, x1, y1, coordZ);
					}

					if (isTrilinearCompareValid(sampler.compare, prec, depths0, depths1,
												Vec2(minA0, maxA0), Vec2(minB0, maxB0),
												Vec2(minA1, maxA1), Vec2(minB1, maxB1),
												fBounds, cmpReference, result, isFixedPointDepth))
						return true;
				}
			}
		}
	}

	return false;
}

static bool isMipmapLinearCompareResultValid (const ConstPixelBufferAccess&		level0,
											  const ConstPixelBufferAccess&		level1,
											  const Sampler&					sampler,
											  const Sampler::FilterMode			levelFilter,
											  const TexComparePrecision&		prec,
											  const Vec2&						coord,
											  const int							coordZ,
											  const Vec2&						fBounds,
											  const float						cmpReference,
											  const float						result)
{
	if (levelFilter == Sampler::LINEAR)
		return isLinearMipmapLinearCompareResultValid(level0, level1, sampler, prec, coord, coordZ, fBounds, cmpReference, result);
	else
		return isNearestMipmapLinearCompareResultValid(level0, level1, sampler, prec, coord, coordZ, fBounds, cmpReference, result);
}

bool isTexCompareResultValid (const Texture2DView&			texture,
							  const Sampler&				sampler,
							  const TexComparePrecision&	prec,
							  const Vec2&					coord,
							  const Vec2&					lodBounds,
							  const float					cmpReference,
							  const float					result)
{
	const float		minLod			= lodBounds.x();
	const float		maxLod			= lodBounds.y();
	const bool		canBeMagnified	= minLod <= sampler.lodThreshold;
	const bool		canBeMinified	= maxLod > sampler.lodThreshold;

	DE_ASSERT(isSamplerSupported(sampler));

	if (canBeMagnified)
	{
		if (isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coord, 0, cmpReference, result))
			return true;
	}

	if (canBeMinified)
	{
		const bool	isNearestMipmap	= isNearestMipmapFilter(sampler.minFilter);
		const bool	isLinearMipmap	= isLinearMipmapFilter(sampler.minFilter);
		const int	minTexLevel		= 0;
		const int	maxTexLevel		= texture.getNumLevels()-1;

		DE_ASSERT(minTexLevel < maxTexLevel);

		if (isLinearMipmap)
		{
			const int		minLevel		= de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel-1);
			const int		maxLevel		= de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel-1);

			DE_ASSERT(minLevel <= maxLevel);

			for (int level = minLevel; level <= maxLevel; level++)
			{
				const float		minF	= de::clamp(minLod - float(level), 0.0f, 1.0f);
				const float		maxF	= de::clamp(maxLod - float(level), 0.0f, 1.0f);

				if (isMipmapLinearCompareResultValid(texture.getLevel(level), texture.getLevel(level+1), sampler, getLevelFilter(sampler.minFilter), prec, coord, 0, Vec2(minF, maxF), cmpReference, result))
					return true;
			}
		}
		else if (isNearestMipmap)
		{
			// \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
			//		 decision to allow floor(lod + 0.5) as well.
			const int		minLevel		= de::clamp((int)deFloatCeil(minLod + 0.5f) - 1,	minTexLevel, maxTexLevel);
			const int		maxLevel		= de::clamp((int)deFloatFloor(maxLod + 0.5f),		minTexLevel, maxTexLevel);

			DE_ASSERT(minLevel <= maxLevel);

			for (int level = minLevel; level <= maxLevel; level++)
			{
				if (isLevelCompareResultValid(texture.getLevel(level), sampler, getLevelFilter(sampler.minFilter), prec, coord, 0, cmpReference, result))
					return true;
			}
		}
		else
		{
			if (isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, coord, 0, cmpReference, result))
				return true;
		}
	}

	return false;
}

static bool isSeamplessLinearMipmapLinearCompareResultValid (const TextureCubeView&			texture,
															 const int						baseLevelNdx,
															 const Sampler&					sampler,
															 const TexComparePrecision&		prec,
															 const CubeFaceFloatCoords&		coords,
															 const Vec2&					fBounds,
															 const float					cmpReference,
															 const float					result)
{
	const bool	isFixedPointDepth	= isFixedPointDepthTextureFormat(texture.getLevelFace(baseLevelNdx, CUBEFACE_NEGATIVE_X).getFormat());
	const int	size0				= texture.getLevelFace(baseLevelNdx,	coords.face).getWidth();
	const int	size1				= texture.getLevelFace(baseLevelNdx+1,	coords.face).getWidth();

	const Vec2	uBounds0			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0,	coords.s, prec.coordBits.x(), prec.uvwBits.x());
	const Vec2	uBounds1			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1,	coords.s, prec.coordBits.x(), prec.uvwBits.x());
	const Vec2	vBounds0			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, size0,	coords.t, prec.coordBits.y(), prec.uvwBits.y());
	const Vec2	vBounds1			= computeNonNormalizedCoordBounds(sampler.normalizedCoords, size1,	coords.t, prec.coordBits.y(), prec.uvwBits.y());

	// Integer coordinates - without wrap mode
	const int	minI0				= deFloorFloatToInt32(uBounds0.x()-0.5f);
	const int	maxI0				= deFloorFloatToInt32(uBounds0.y()-0.5f);
	const int	minI1				= deFloorFloatToInt32(uBounds1.x()-0.5f);
	const int	maxI1				= deFloorFloatToInt32(uBounds1.y()-0.5f);
	const int	minJ0				= deFloorFloatToInt32(vBounds0.x()-0.5f);
	const int	maxJ0				= deFloorFloatToInt32(vBounds0.y()-0.5f);
	const int	minJ1				= deFloorFloatToInt32(vBounds1.x()-0.5f);
	const int	maxJ1				= deFloorFloatToInt32(vBounds1.y()-0.5f);

	tcu::ConstPixelBufferAccess faces0[CUBEFACE_LAST];
	tcu::ConstPixelBufferAccess faces1[CUBEFACE_LAST];

	for (int face = 0; face < CUBEFACE_LAST; face++)
	{
		faces0[face] = texture.getLevelFace(baseLevelNdx,	CubeFace(face));
		faces1[face] = texture.getLevelFace(baseLevelNdx+1,	CubeFace(face));
	}

	for (int j0 = minJ0; j0 <= maxJ0; j0++)
	{
		for (int i0 = minI0; i0 <= maxI0; i0++)
		{
			const float	minA0	= de::clamp((uBounds0.x()-0.5f)-float(i0), 0.0f, 1.0f);
			const float	maxA0	= de::clamp((uBounds0.y()-0.5f)-float(i0), 0.0f, 1.0f);
			const float	minB0	= de::clamp((vBounds0.x()-0.5f)-float(j0), 0.0f, 1.0f);
			const float	maxB0	= de::clamp((vBounds0.y()-0.5f)-float(j0), 0.0f, 1.0f);
			Vec4		depths0;

			{
				const CubeFaceIntCoords	c00	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i0+0, j0+0)), size0);
				const CubeFaceIntCoords	c10	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i0+1, j0+0)), size0);
				const CubeFaceIntCoords	c01	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i0+0, j0+1)), size0);
				const CubeFaceIntCoords	c11	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i0+1, j0+1)), size0);

				// If any of samples is out of both edges, implementations can do pretty much anything according to spec.
				// \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color.
				if (c00.face == CUBEFACE_LAST || c01.face == CUBEFACE_LAST || c10.face == CUBEFACE_LAST || c11.face == CUBEFACE_LAST)
					return true;

				depths0[0] = lookupDepthNoBorder(faces0[c00.face], sampler, c00.s, c00.t);
				depths0[1] = lookupDepthNoBorder(faces0[c10.face], sampler, c10.s, c10.t);
				depths0[2] = lookupDepthNoBorder(faces0[c01.face], sampler, c01.s, c01.t);
				depths0[3] = lookupDepthNoBorder(faces0[c11.face], sampler, c11.s, c11.t);
			}

			for (int j1 = minJ1; j1 <= maxJ1; j1++)
			{
				for (int i1 = minI1; i1 <= maxI1; i1++)
				{
					const float	minA1	= de::clamp((uBounds1.x()-0.5f)-float(i1), 0.0f, 1.0f);
					const float	maxA1	= de::clamp((uBounds1.y()-0.5f)-float(i1), 0.0f, 1.0f);
					const float	minB1	= de::clamp((vBounds1.x()-0.5f)-float(j1), 0.0f, 1.0f);
					const float	maxB1	= de::clamp((vBounds1.y()-0.5f)-float(j1), 0.0f, 1.0f);
					Vec4		depths1;

					{
						const CubeFaceIntCoords	c00	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i1+0, j1+0)), size1);
						const CubeFaceIntCoords	c10	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i1+1, j1+0)), size1);
						const CubeFaceIntCoords	c01	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i1+0, j1+1)), size1);
						const CubeFaceIntCoords	c11	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i1+1, j1+1)), size1);

						if (c00.face == CUBEFACE_LAST || c01.face == CUBEFACE_LAST || c10.face == CUBEFACE_LAST || c11.face == CUBEFACE_LAST)
							return true;

						depths1[0] = lookupDepthNoBorder(faces1[c00.face], sampler, c00.s, c00.t);
						depths1[1] = lookupDepthNoBorder(faces1[c10.face], sampler, c10.s, c10.t);
						depths1[2] = lookupDepthNoBorder(faces1[c01.face], sampler, c01.s, c01.t);
						depths1[3] = lookupDepthNoBorder(faces1[c11.face], sampler, c11.s, c11.t);
					}


					if (isTrilinearCompareValid(sampler.compare, prec, depths0, depths1,
												Vec2(minA0, maxA0), Vec2(minB0, maxB0),
												Vec2(minA1, maxA1), Vec2(minB1, maxB1),
												fBounds, cmpReference, result, isFixedPointDepth))
						return true;
				}
			}
		}
	}

	return false;
}

static bool isCubeMipmapLinearCompareResultValid (const TextureCubeView&		texture,
												  const int						baseLevelNdx,
												  const Sampler&				sampler,
												  const Sampler::FilterMode		levelFilter,
												  const TexComparePrecision&	prec,
												  const CubeFaceFloatCoords&	coords,
												  const Vec2&					fBounds,
												  const float					cmpReference,
												  const float					result)
{
	if (levelFilter == Sampler::LINEAR)
	{
		if (sampler.seamlessCubeMap)
			return isSeamplessLinearMipmapLinearCompareResultValid(texture, baseLevelNdx, sampler, prec, coords, fBounds, cmpReference, result);
		else
			return isLinearMipmapLinearCompareResultValid(texture.getLevelFace(baseLevelNdx,	coords.face),
														  texture.getLevelFace(baseLevelNdx+1,	coords.face),
														  sampler, prec, Vec2(coords.s, coords.t), 0, fBounds, cmpReference, result);
	}
	else
		return isNearestMipmapLinearCompareResultValid(texture.getLevelFace(baseLevelNdx,	coords.face),
													   texture.getLevelFace(baseLevelNdx+1,	coords.face),
													   sampler, prec, Vec2(coords.s, coords.t), 0, fBounds, cmpReference, result);
}

static bool isSeamlessLinearCompareResultValid (const TextureCubeView&		texture,
												const int					levelNdx,
												const Sampler&				sampler,
												const TexComparePrecision&	prec,
												const CubeFaceFloatCoords&	coords,
												const float					cmpReference,
												const float					result)
{
	const bool	isFixedPointDepth	= isFixedPointDepthTextureFormat(texture.getLevelFace(levelNdx, CUBEFACE_NEGATIVE_X).getFormat());
	const int	size				= texture.getLevelFace(levelNdx, coords.face).getWidth();

	const Vec2	uBounds				= computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.s, prec.coordBits.x(), prec.uvwBits.x());
	const Vec2	vBounds				= computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.t, prec.coordBits.y(), prec.uvwBits.y());

	// Integer coordinate bounds for (x0,y0) - without wrap mode
	const int	minI				= deFloorFloatToInt32(uBounds.x()-0.5f);
	const int	maxI				= deFloorFloatToInt32(uBounds.y()-0.5f);
	const int	minJ				= deFloorFloatToInt32(vBounds.x()-0.5f);
	const int	maxJ				= deFloorFloatToInt32(vBounds.y()-0.5f);

	// Face accesses
	ConstPixelBufferAccess faces[CUBEFACE_LAST];
	for (int face = 0; face < CUBEFACE_LAST; face++)
		faces[face] = texture.getLevelFace(levelNdx, CubeFace(face));

	for (int j = minJ; j <= maxJ; j++)
	{
		for (int i = minI; i <= maxI; i++)
		{
			const CubeFaceIntCoords	c00	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i+0, j+0)), size);
			const CubeFaceIntCoords	c10	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i+1, j+0)), size);
			const CubeFaceIntCoords	c01	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i+0, j+1)), size);
			const CubeFaceIntCoords	c11	= remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, IVec2(i+1, j+1)), size);

			// If any of samples is out of both edges, implementations can do pretty much anything according to spec.
			// \todo [2013-07-08 pyry] Test the special case where all corner pixels have exactly the same color.
			if (c00.face == CUBEFACE_LAST || c01.face == CUBEFACE_LAST || c10.face == CUBEFACE_LAST || c11.face == CUBEFACE_LAST)
				return true;

			// Bounds for filtering factors
			const float	minA	= de::clamp((uBounds.x()-0.5f)-float(i), 0.0f, 1.0f);
			const float	maxA	= de::clamp((uBounds.y()-0.5f)-float(i), 0.0f, 1.0f);
			const float	minB	= de::clamp((vBounds.x()-0.5f)-float(j), 0.0f, 1.0f);
			const float	maxB	= de::clamp((vBounds.y()-0.5f)-float(j), 0.0f, 1.0f);

			Vec4 depths;
			depths[0] = lookupDepthNoBorder(faces[c00.face], sampler, c00.s, c00.t);
			depths[1] = lookupDepthNoBorder(faces[c10.face], sampler, c10.s, c10.t);
			depths[2] = lookupDepthNoBorder(faces[c01.face], sampler, c01.s, c01.t);
			depths[3] = lookupDepthNoBorder(faces[c11.face], sampler, c11.s, c11.t);

			if (isBilinearCompareValid(sampler.compare, prec, depths, Vec2(minA, maxA), Vec2(minB, maxB), cmpReference, result, isFixedPointDepth))
				return true;
		}
	}

	return false;
}

static bool isCubeLevelCompareResultValid (const TextureCubeView&			texture,
										   const int						levelNdx,
										   const Sampler&					sampler,
										   const Sampler::FilterMode		filterMode,
										   const TexComparePrecision&		prec,
										   const CubeFaceFloatCoords&		coords,
										   const float						cmpReference,
										   const float						result)
{
	if (filterMode == Sampler::LINEAR)
	{
		if (sampler.seamlessCubeMap)
			return isSeamlessLinearCompareResultValid(texture, levelNdx, sampler, prec, coords, cmpReference, result);
		else
			return isLinearCompareResultValid(texture.getLevelFace(levelNdx, coords.face), sampler, prec, Vec2(coords.s, coords.t), 0, cmpReference, result);
	}
	else
		return isNearestCompareResultValid(texture.getLevelFace(levelNdx, coords.face), sampler, prec, Vec2(coords.s, coords.t), 0, cmpReference, result);
}

bool isTexCompareResultValid (const TextureCubeView& texture, const Sampler& sampler, const TexComparePrecision& prec, const Vec3& coord, const Vec2& lodBounds, const float cmpReference, const float result)
{
	int			numPossibleFaces				= 0;
	CubeFace	possibleFaces[CUBEFACE_LAST];

	DE_ASSERT(isSamplerSupported(sampler));

	getPossibleCubeFaces(coord, prec.coordBits, &possibleFaces[0], numPossibleFaces);

	if (numPossibleFaces == 0)
		return true; // Result is undefined.

	for (int tryFaceNdx = 0; tryFaceNdx < numPossibleFaces; tryFaceNdx++)
	{
		const CubeFaceFloatCoords	faceCoords		(possibleFaces[tryFaceNdx], projectToFace(possibleFaces[tryFaceNdx], coord));
		const float					minLod			= lodBounds.x();
		const float					maxLod			= lodBounds.y();
		const bool					canBeMagnified	= minLod <= sampler.lodThreshold;
		const bool					canBeMinified	= maxLod > sampler.lodThreshold;

		if (canBeMagnified)
		{
			if (isCubeLevelCompareResultValid(texture, 0, sampler, sampler.magFilter, prec, faceCoords, cmpReference, result))
				return true;
		}

		if (canBeMinified)
		{
			const bool	isNearestMipmap	= isNearestMipmapFilter(sampler.minFilter);
			const bool	isLinearMipmap	= isLinearMipmapFilter(sampler.minFilter);
			const int	minTexLevel		= 0;
			const int	maxTexLevel		= texture.getNumLevels()-1;

			DE_ASSERT(minTexLevel < maxTexLevel);

			if (isLinearMipmap)
			{
				const int		minLevel		= de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel-1);
				const int		maxLevel		= de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel-1);

				DE_ASSERT(minLevel <= maxLevel);

				for (int level = minLevel; level <= maxLevel; level++)
				{
					const float		minF	= de::clamp(minLod - float(level), 0.0f, 1.0f);
					const float		maxF	= de::clamp(maxLod - float(level), 0.0f, 1.0f);

					if (isCubeMipmapLinearCompareResultValid(texture, level, sampler, getLevelFilter(sampler.minFilter), prec, faceCoords, Vec2(minF, maxF), cmpReference, result))
						return true;
				}
			}
			else if (isNearestMipmap)
			{
				// \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
				//		 decision to allow floor(lod + 0.5) as well.
				const int		minLevel		= de::clamp((int)deFloatCeil(minLod + 0.5f) - 1,	minTexLevel, maxTexLevel);
				const int		maxLevel		= de::clamp((int)deFloatFloor(maxLod + 0.5f),		minTexLevel, maxTexLevel);

				DE_ASSERT(minLevel <= maxLevel);

				for (int level = minLevel; level <= maxLevel; level++)
				{
					if (isCubeLevelCompareResultValid(texture, level, sampler, getLevelFilter(sampler.minFilter), prec, faceCoords, cmpReference, result))
						return true;
				}
			}
			else
			{
				if (isCubeLevelCompareResultValid(texture, 0, sampler, sampler.minFilter, prec, faceCoords, cmpReference, result))
					return true;
			}
		}
	}

	return false;
}

bool isTexCompareResultValid (const Texture2DArrayView& texture, const Sampler& sampler, const TexComparePrecision& prec, const Vec3& coord, const Vec2& lodBounds, const float cmpReference, const float result)
{
	const float		depthErr	= computeFloatingPointError(coord.z(), prec.coordBits.z()) + computeFixedPointError(prec.uvwBits.z());
	const float		minZ		= coord.z()-depthErr;
	const float		maxZ		= coord.z()+depthErr;
	const int		minLayer	= de::clamp(deFloorFloatToInt32(minZ + 0.5f), 0, texture.getNumLayers()-1);
	const int		maxLayer	= de::clamp(deFloorFloatToInt32(maxZ + 0.5f), 0, texture.getNumLayers()-1);

	DE_ASSERT(isSamplerSupported(sampler));

	for (int layer = minLayer; layer <= maxLayer; layer++)
	{
		const float		minLod			= lodBounds.x();
		const float		maxLod			= lodBounds.y();
		const bool		canBeMagnified	= minLod <= sampler.lodThreshold;
		const bool		canBeMinified	= maxLod > sampler.lodThreshold;

		if (canBeMagnified)
		{
			if (isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.magFilter, prec, coord.swizzle(0,1), layer, cmpReference, result))
				return true;
		}

		if (canBeMinified)
		{
			const bool	isNearestMipmap	= isNearestMipmapFilter(sampler.minFilter);
			const bool	isLinearMipmap	= isLinearMipmapFilter(sampler.minFilter);
			const int	minTexLevel		= 0;
			const int	maxTexLevel		= texture.getNumLevels()-1;

			DE_ASSERT(minTexLevel < maxTexLevel);

			if (isLinearMipmap)
			{
				const int		minLevel		= de::clamp((int)deFloatFloor(minLod), minTexLevel, maxTexLevel-1);
				const int		maxLevel		= de::clamp((int)deFloatFloor(maxLod), minTexLevel, maxTexLevel-1);

				DE_ASSERT(minLevel <= maxLevel);

				for (int level = minLevel; level <= maxLevel; level++)
				{
					const float		minF	= de::clamp(minLod - float(level), 0.0f, 1.0f);
					const float		maxF	= de::clamp(maxLod - float(level), 0.0f, 1.0f);

					if (isMipmapLinearCompareResultValid(texture.getLevel(level), texture.getLevel(level+1), sampler, getLevelFilter(sampler.minFilter), prec, coord.swizzle(0,1), layer, Vec2(minF, maxF), cmpReference, result))
						return true;
				}
			}
			else if (isNearestMipmap)
			{
				// \note The accurate formula for nearest mipmapping is level = ceil(lod + 0.5) - 1 but Khronos has made
				//		 decision to allow floor(lod + 0.5) as well.
				const int		minLevel		= de::clamp((int)deFloatCeil(minLod + 0.5f) - 1,	minTexLevel, maxTexLevel);
				const int		maxLevel		= de::clamp((int)deFloatFloor(maxLod + 0.5f),		minTexLevel, maxTexLevel);

				DE_ASSERT(minLevel <= maxLevel);

				for (int level = minLevel; level <= maxLevel; level++)
				{
					if (isLevelCompareResultValid(texture.getLevel(level), sampler, getLevelFilter(sampler.minFilter), prec, coord.swizzle(0,1), layer, cmpReference, result))
						return true;
				}
			}
			else
			{
				if (isLevelCompareResultValid(texture.getLevel(0), sampler, sampler.minFilter, prec, coord.swizzle(0,1), layer, cmpReference, result))
					return true;
			}
		}
	}

	return false;
}

static bool isGatherOffsetsCompareResultValid (const ConstPixelBufferAccess&	texture,
											   const Sampler&					sampler,
											   const TexComparePrecision&		prec,
											   const Vec2&						coord,
											   int								coordZ,
											   const IVec2						(&offsets)[4],
											   float							cmpReference,
											   const Vec4&						result)
{
	const bool	isFixedPointDepth	= isFixedPointDepthTextureFormat(texture.getFormat());
	const Vec2	uBounds				= computeNonNormalizedCoordBounds(sampler.normalizedCoords, texture.getWidth(),		coord.x(), prec.coordBits.x(), prec.uvwBits.x());
	const Vec2	vBounds				= computeNonNormalizedCoordBounds(sampler.normalizedCoords, texture.getHeight(),	coord.y(), prec.coordBits.y(), prec.uvwBits.y());

	// Integer coordinate bounds for (x0, y0) - without wrap mode
	const int	minI				= deFloorFloatToInt32(uBounds.x()-0.5f);
	const int	maxI				= deFloorFloatToInt32(uBounds.y()-0.5f);
	const int	minJ				= deFloorFloatToInt32(vBounds.x()-0.5f);
	const int	maxJ				= deFloorFloatToInt32(vBounds.y()-0.5f);

	const int	w					= texture.getWidth();
	const int	h					= texture.getHeight();

	for (int j = minJ; j <= maxJ; j++)
	{
		for (int i = minI; i <= maxI; i++)
		{
			bool isCurrentPixelValid = true;

			for (int offNdx = 0; offNdx < 4 && isCurrentPixelValid; offNdx++)
			{
				// offNdx-th coordinate offset and then wrapped.
				const int			x		= wrap(sampler.wrapS, i+offsets[offNdx].x(), w);
				const int			y		= wrap(sampler.wrapT, j+offsets[offNdx].y(), h);
				const float			depth	= lookupDepth(texture, sampler, x, y, coordZ);
				const CmpResultSet	resSet	= execCompare(sampler.compare, depth, cmpReference, prec.referenceBits, isFixedPointDepth);

				if (!isResultInSet(resSet, result[offNdx], prec.resultBits))
					isCurrentPixelValid = false;
			}

			if (isCurrentPixelValid)
				return true;
		}
	}

	return false;
}

bool isGatherOffsetsCompareResultValid (const Texture2DView&		texture,
										const Sampler&				sampler,
										const TexComparePrecision&	prec,
										const Vec2&					coord,
										const IVec2					(&offsets)[4],
										float						cmpReference,
										const Vec4&					result)
{
	DE_ASSERT(isSamplerSupported(sampler));

	return isGatherOffsetsCompareResultValid(texture.getLevel(0), sampler, prec, coord, 0, offsets, cmpReference, result);
}

bool isGatherOffsetsCompareResultValid (const Texture2DArrayView&	texture,
										const Sampler&				sampler,
										const TexComparePrecision&	prec,
										const Vec3&					coord,
										const IVec2					(&offsets)[4],
										float						cmpReference,
										const Vec4&					result)
{
	const float		depthErr	= computeFloatingPointError(coord.z(), prec.coordBits.z()) + computeFixedPointError(prec.uvwBits.z());
	const float		minZ		= coord.z()-depthErr;
	const float		maxZ		= coord.z()+depthErr;
	const int		minLayer	= de::clamp(deFloorFloatToInt32(minZ + 0.5f), 0, texture.getNumLayers()-1);
	const int		maxLayer	= de::clamp(deFloorFloatToInt32(maxZ + 0.5f), 0, texture.getNumLayers()-1);

	DE_ASSERT(isSamplerSupported(sampler));

	for (int layer = minLayer; layer <= maxLayer; layer++)
	{
		if (isGatherOffsetsCompareResultValid(texture.getLevel(0), sampler, prec, coord.swizzle(0,1), layer, offsets, cmpReference, result))
			return true;
	}
	return false;
}

static bool isGatherCompareResultValid (const TextureCubeView&		texture,
										const Sampler&				sampler,
										const TexComparePrecision&	prec,
										const CubeFaceFloatCoords&	coords,
										float						cmpReference,
										const Vec4&					result)
{
	const bool	isFixedPointDepth	= isFixedPointDepthTextureFormat(texture.getLevelFace(0, coords.face).getFormat());
	const int	size				= texture.getLevelFace(0, coords.face).getWidth();
	const Vec2	uBounds				= computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.s, prec.coordBits.x(), prec.uvwBits.x());
	const Vec2	vBounds				= computeNonNormalizedCoordBounds(sampler.normalizedCoords, size, coords.t, prec.coordBits.y(), prec.uvwBits.y());

	// Integer coordinate bounds for (x0,y0) - without wrap mode
	const int	minI				= deFloorFloatToInt32(uBounds.x()-0.5f);
	const int	maxI				= deFloorFloatToInt32(uBounds.y()-0.5f);
	const int	minJ				= deFloorFloatToInt32(vBounds.x()-0.5f);
	const int	maxJ				= deFloorFloatToInt32(vBounds.y()-0.5f);

	// Face accesses
	ConstPixelBufferAccess faces[CUBEFACE_LAST];
	for (int face = 0; face < CUBEFACE_LAST; face++)
		faces[face] = texture.getLevelFace(0, CubeFace(face));

	for (int j = minJ; j <= maxJ; j++)
	{
		for (int i = minI; i <= maxI; i++)
		{
			static const IVec2 offsets[4] =
			{
				IVec2(0, 1),
				IVec2(1, 1),
				IVec2(1, 0),
				IVec2(0, 0)
			};

			bool isCurrentPixelValid = true;

			for (int offNdx = 0; offNdx < 4 && isCurrentPixelValid; offNdx++)
			{
				const CubeFaceIntCoords c = remapCubeEdgeCoords(CubeFaceIntCoords(coords.face, i+offsets[offNdx].x(), j+offsets[offNdx].y()), size);
				// If any of samples is out of both edges, implementations can do pretty much anything according to spec.
				// \todo [2014-06-05 nuutti] Test the special case where all corner pixels have exactly the same color.
				//							 See also isSeamlessLinearCompareResultValid and similar.
				if (c.face == CUBEFACE_LAST)
					return true;

				const float			depth	= lookupDepthNoBorder(faces[c.face], sampler, c.s, c.t);
				const CmpResultSet	resSet	= execCompare(sampler.compare, depth, cmpReference, prec.referenceBits, isFixedPointDepth);

				if (!isResultInSet(resSet, result[offNdx], prec.resultBits))
					isCurrentPixelValid = false;
			}

			if (isCurrentPixelValid)
				return true;
		}
	}

	return false;
}

bool isGatherCompareResultValid (const TextureCubeView&			texture,
								 const Sampler&					sampler,
								 const TexComparePrecision&		prec,
								 const Vec3&					coord,
								 float							cmpReference,
								 const Vec4&					result)
{
	int			numPossibleFaces				= 0;
	CubeFace	possibleFaces[CUBEFACE_LAST];

	DE_ASSERT(isSamplerSupported(sampler));

	getPossibleCubeFaces(coord, prec.coordBits, &possibleFaces[0], numPossibleFaces);

	if (numPossibleFaces == 0)
		return true; // Result is undefined.

	for (int tryFaceNdx = 0; tryFaceNdx < numPossibleFaces; tryFaceNdx++)
	{
		const CubeFaceFloatCoords faceCoords(possibleFaces[tryFaceNdx], projectToFace(possibleFaces[tryFaceNdx], coord));

		if (isGatherCompareResultValid(texture, sampler, prec, faceCoords, cmpReference, result))
			return true;
	}

	return false;
}

} // tcu
