/*-------------------------------------------------------------------------
 * 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 utilities.
 *//*--------------------------------------------------------------------*/

#include "tcuTextureUtil.hpp"
#include "tcuVectorUtil.hpp"
#include "deRandom.hpp"
#include "deMath.h"
#include "deMemory.h"

#include <limits>

namespace tcu
{

static inline float sRGBChannelToLinear (float cs)
{
	if (cs <= 0.04045)
		return cs / 12.92f;
	else
		return deFloatPow((cs + 0.055f) / 1.055f, 2.4f);
}

static const deUint32 s_srgb8Lut[256] =
{
#include "tcuSRGB8Lut.inl"
};

static inline float sRGB8ChannelToLinear (deUint32 cs)
{
	DE_ASSERT(cs < 256);

	// \note This triggers UB, but in practice it doesn't cause any problems
	return ((const float*)s_srgb8Lut)[cs];
}

static inline float linearChannelToSRGB (float cl)
{
	if (cl <= 0.0f)
		return 0.0f;
	else if (cl < 0.0031308f)
		return 12.92f*cl;
	else if (cl < 1.0f)
		return 1.055f*deFloatPow(cl, 0.41666f) - 0.055f;
	else
		return 1.0f;
}

//! Convert sRGB to linear colorspace
Vec4 sRGBToLinear (const Vec4& cs)
{
	return Vec4(sRGBChannelToLinear(cs[0]),
				sRGBChannelToLinear(cs[1]),
				sRGBChannelToLinear(cs[2]),
				cs[3]);
}

Vec4 sRGB8ToLinear (const UVec4& cs)
{
	return Vec4(sRGB8ChannelToLinear(cs[0]),
				sRGB8ChannelToLinear(cs[1]),
				sRGB8ChannelToLinear(cs[2]),
				1.0f);
}

Vec4 sRGBA8ToLinear (const UVec4& cs)
{
	return Vec4(sRGB8ChannelToLinear(cs[0]),
				sRGB8ChannelToLinear(cs[1]),
				sRGB8ChannelToLinear(cs[2]),
				(float)cs[3] / 255.0f);
}

//! Convert from linear to sRGB colorspace
Vec4 linearToSRGB (const Vec4& cl)
{
	return Vec4(linearChannelToSRGB(cl[0]),
				linearChannelToSRGB(cl[1]),
				linearChannelToSRGB(cl[2]),
				cl[3]);
}

bool isSRGB (TextureFormat format)
{
	// make sure to update this if type table is updated
	DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 21);

	return	format.order == TextureFormat::sR		||
			format.order == TextureFormat::sRG		||
			format.order == TextureFormat::sRGB		||
			format.order == TextureFormat::sRGBA	||
			format.order == TextureFormat::sBGR		||
			format.order == TextureFormat::sBGRA;
}

tcu::Vec4 linearToSRGBIfNeeded (const TextureFormat& format, const tcu::Vec4& color)
{
	return isSRGB(format) ? linearToSRGB(color) : color;
}

bool isCombinedDepthStencilType (TextureFormat::ChannelType type)
{
	// make sure to update this if type table is updated
	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40);

	return	type == TextureFormat::UNSIGNED_INT_16_8_8			||
			type == TextureFormat::UNSIGNED_INT_24_8			||
			type == TextureFormat::UNSIGNED_INT_24_8_REV		||
			type == TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV;
}

bool hasStencilComponent (TextureFormat::ChannelOrder order)
{
	DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 21);

	switch (order)
	{
		case TextureFormat::S:
		case TextureFormat::DS:
			return true;

		default:
			return false;
	}
}

bool hasDepthComponent (TextureFormat::ChannelOrder order)
{
	DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 21);

	switch (order)
	{
		case TextureFormat::D:
		case TextureFormat::DS:
			return true;

		default:
			return false;
	}
}

//! Get texture channel class for format
TextureChannelClass getTextureChannelClass (TextureFormat::ChannelType channelType)
{
	// make sure this table is updated if format table is updated
	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40);

	switch (channelType)
	{
		case TextureFormat::SNORM_INT8:						return TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
		case TextureFormat::SNORM_INT16:					return TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
		case TextureFormat::SNORM_INT32:					return TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
		case TextureFormat::UNORM_INT8:						return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
		case TextureFormat::UNORM_INT16:					return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
		case TextureFormat::UNORM_INT24:					return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
		case TextureFormat::UNORM_INT32:					return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
		case TextureFormat::UNORM_BYTE_44:					return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
		case TextureFormat::UNORM_SHORT_565:				return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
		case TextureFormat::UNORM_SHORT_555:				return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
		case TextureFormat::UNORM_SHORT_4444:				return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
		case TextureFormat::UNORM_SHORT_5551:				return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
		case TextureFormat::UNORM_SHORT_1555:				return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
		case TextureFormat::UNSIGNED_BYTE_44:				return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
		case TextureFormat::UNSIGNED_SHORT_565:				return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
		case TextureFormat::UNSIGNED_SHORT_4444:			return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
		case TextureFormat::UNSIGNED_SHORT_5551:			return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
		case TextureFormat::UNORM_INT_101010:				return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
		case TextureFormat::SNORM_INT_1010102_REV:			return TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
		case TextureFormat::UNORM_INT_1010102_REV:			return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
		case TextureFormat::SIGNED_INT_1010102_REV:			return TEXTURECHANNELCLASS_SIGNED_INTEGER;
		case TextureFormat::UNSIGNED_INT_1010102_REV:		return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:	return TEXTURECHANNELCLASS_FLOATING_POINT;
		case TextureFormat::UNSIGNED_INT_999_E5_REV:		return TEXTURECHANNELCLASS_FLOATING_POINT;
		case TextureFormat::UNSIGNED_INT_16_8_8:			return TEXTURECHANNELCLASS_LAST;					//!< packed unorm16-x8-uint8
		case TextureFormat::UNSIGNED_INT_24_8:				return TEXTURECHANNELCLASS_LAST;					//!< packed unorm24-uint8
		case TextureFormat::UNSIGNED_INT_24_8_REV:			return TEXTURECHANNELCLASS_LAST;					//!< packed unorm24-uint8
		case TextureFormat::SIGNED_INT8:					return TEXTURECHANNELCLASS_SIGNED_INTEGER;
		case TextureFormat::SIGNED_INT16:					return TEXTURECHANNELCLASS_SIGNED_INTEGER;
		case TextureFormat::SIGNED_INT32:					return TEXTURECHANNELCLASS_SIGNED_INTEGER;
		case TextureFormat::UNSIGNED_INT8:					return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
		case TextureFormat::UNSIGNED_INT16:					return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
		case TextureFormat::UNSIGNED_INT24:					return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
		case TextureFormat::UNSIGNED_INT32:					return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
		case TextureFormat::HALF_FLOAT:						return TEXTURECHANNELCLASS_FLOATING_POINT;
		case TextureFormat::FLOAT:							return TEXTURECHANNELCLASS_FLOATING_POINT;
		case TextureFormat::FLOAT64:						return TEXTURECHANNELCLASS_FLOATING_POINT;
		case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:	return TEXTURECHANNELCLASS_LAST;					//!< packed float32-pad24-uint8
		case TextureFormat::UNORM_SHORT_10:					return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
		case TextureFormat::UNORM_SHORT_12:					return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
		default:
			DE_FATAL("Unknown channel type");
			return TEXTURECHANNELCLASS_LAST;
	}
}

bool isAccessValid (TextureFormat format, TextureAccessType type)
{
	DE_ASSERT(isValid(format));

	if (format.order == TextureFormat::DS)
	{
		// It is never allowed to access combined depth-stencil format with getPixel().
		// Instead either getPixDepth() or getPixStencil(), or effective depth- or stencil-
		// access must be used.
		return false;
	}
	else if (format.order == TextureFormat::D)
		return type == TEXTUREACCESSTYPE_FLOAT;
	else if (format.order == TextureFormat::S)
		return type == TEXTUREACCESSTYPE_UNSIGNED_INT;
	else
	{
		// A few packed color formats have access type restrictions
		if (format.type == TextureFormat::UNSIGNED_INT_11F_11F_10F_REV ||
			format.type == TextureFormat::UNSIGNED_INT_999_E5_REV)
			return type == TEXTUREACCESSTYPE_FLOAT;
		else
			return true;
	}
}

/*--------------------------------------------------------------------*//*!
 * \brief Get access to subregion of pixel buffer
 * \param access	Parent access object
 * \param x			X offset
 * \param y			Y offset
 * \param z			Z offset
 * \param width		Width
 * \param height	Height
 * \param depth		Depth
 * \return Access object that targets given subregion of parent access object
 *//*--------------------------------------------------------------------*/
ConstPixelBufferAccess getSubregion (const ConstPixelBufferAccess& access, int x, int y, int z, int width, int height, int depth)
{
	DE_ASSERT(de::inBounds(x, 0, access.getWidth()));
	DE_ASSERT(de::inRange(x+width, x+1, access.getWidth()));

	DE_ASSERT(de::inBounds(y, 0, access.getHeight()));
	DE_ASSERT(de::inRange(y+height, y+1, access.getHeight()));

	DE_ASSERT(de::inBounds(z, 0, access.getDepth()));
	DE_ASSERT(de::inRange(z+depth, z+1, access.getDepth()));

	return ConstPixelBufferAccess(access.getFormat(), tcu::IVec3(width, height, depth), access.getPitch(),
								  (const deUint8*)access.getDataPtr() + access.getPixelPitch()*x + access.getRowPitch()*y + access.getSlicePitch()*z);
}

/*--------------------------------------------------------------------*//*!
 * \brief Get access to subregion of pixel buffer
 * \param access	Parent access object
 * \param x			X offset
 * \param y			Y offset
 * \param z			Z offset
 * \param width		Width
 * \param height	Height
 * \param depth		Depth
 * \return Access object that targets given subregion of parent access object
 *//*--------------------------------------------------------------------*/
PixelBufferAccess getSubregion (const PixelBufferAccess& access, int x, int y, int z, int width, int height, int depth)
{
	DE_ASSERT(de::inBounds(x, 0, access.getWidth()));
	DE_ASSERT(de::inRange(x+width, x+1, access.getWidth()));

	DE_ASSERT(de::inBounds(y, 0, access.getHeight()));
	DE_ASSERT(de::inRange(y+height, y+1, access.getHeight()));

	DE_ASSERT(de::inBounds(z, 0, access.getDepth()));
	DE_ASSERT(de::inRange(z+depth, z+1, access.getDepth()));

	return PixelBufferAccess(access.getFormat(), tcu::IVec3(width, height, depth), access.getPitch(),
							 (deUint8*)access.getDataPtr() + access.getPixelPitch()*x + access.getRowPitch()*y + access.getSlicePitch()*z);
}

/*--------------------------------------------------------------------*//*!
 * \brief Get access to subregion of pixel buffer
 * \param access	Parent access object
 * \param x			X offset
 * \param y			Y offset
 * \param width		Width
 * \param height	Height
 * \return Access object that targets given subregion of parent access object
 *//*--------------------------------------------------------------------*/
PixelBufferAccess getSubregion (const PixelBufferAccess& access, int x, int y, int width, int height)
{
	return getSubregion(access, x, y, 0, width, height, 1);
}

/*--------------------------------------------------------------------*//*!
 * \brief Get access to subregion of pixel buffer
 * \param access	Parent access object
 * \param x			X offset
 * \param y			Y offset
 * \param width		Width
 * \param height	Height
 * \return Access object that targets given subregion of parent access object
 *//*--------------------------------------------------------------------*/
ConstPixelBufferAccess getSubregion (const ConstPixelBufferAccess& access, int x, int y, int width, int height)
{
	return getSubregion(access, x, y, 0, width, height, 1);
}

/*--------------------------------------------------------------------*//*!
 * \brief Flip rows in Y direction
 * \param access Access object
 * \return Modified access object where Y coordinates are reversed
 *//*--------------------------------------------------------------------*/
PixelBufferAccess flipYAccess (const PixelBufferAccess& access)
{
	const int			rowPitch		= access.getRowPitch();
	const int			offsetToLast	= rowPitch*(access.getHeight()-1);
	const tcu::IVec3	pitch			(access.getPixelPitch(), -rowPitch, access.getSlicePitch());

	return PixelBufferAccess(access.getFormat(), access.getSize(), pitch, (deUint8*)access.getDataPtr() + offsetToLast);
}

/*--------------------------------------------------------------------*//*!
 * \brief Flip rows in Y direction
 * \param access Access object
 * \return Modified access object where Y coordinates are reversed
 *//*--------------------------------------------------------------------*/
ConstPixelBufferAccess flipYAccess (const ConstPixelBufferAccess& access)
{
	const int			rowPitch		= access.getRowPitch();
	const int			offsetToLast	= rowPitch*(access.getHeight()-1);
	const tcu::IVec3	pitch			(access.getPixelPitch(), -rowPitch, access.getSlicePitch());

	return ConstPixelBufferAccess(access.getFormat(), access.getSize(), pitch, (deUint8*)access.getDataPtr() + offsetToLast);
}

static Vec2 getFloatChannelValueRange (TextureFormat::ChannelType channelType)
{
	// make sure this table is updated if format table is updated
	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40);

	float cMin = 0.0f;
	float cMax = 0.0f;

	switch (channelType)
	{
		// Signed normalized formats.
		case TextureFormat::SNORM_INT8:
		case TextureFormat::SNORM_INT16:
		case TextureFormat::SNORM_INT32:
		case TextureFormat::SNORM_INT_1010102_REV:			cMin = -1.0f;			cMax = 1.0f;			break;

		// Unsigned normalized formats.
		case TextureFormat::UNORM_INT8:
		case TextureFormat::UNORM_INT16:
		case TextureFormat::UNORM_INT24:
		case TextureFormat::UNORM_INT32:
		case TextureFormat::UNORM_BYTE_44:
		case TextureFormat::UNORM_SHORT_565:
		case TextureFormat::UNORM_SHORT_555:
		case TextureFormat::UNORM_SHORT_4444:
		case TextureFormat::UNORM_SHORT_5551:
		case TextureFormat::UNORM_SHORT_1555:
		case TextureFormat::UNORM_INT_101010:
		case TextureFormat::UNORM_INT_1010102_REV:
		case TextureFormat::UNORM_SHORT_10:
		case TextureFormat::UNORM_SHORT_12:					cMin = 0.0f;			cMax = 1.0f;			break;

		// Misc formats.
		case TextureFormat::SIGNED_INT8:					cMin = -128.0f;			cMax = 127.0f;			break;
		case TextureFormat::SIGNED_INT16:					cMin = -32768.0f;		cMax = 32767.0f;		break;
		case TextureFormat::SIGNED_INT32:					cMin = -2147483520.0f;	cMax = 2147483520.0f;	break; // Maximum exactly representable 31-bit integer: (2^24 - 1) * 2^7
		case TextureFormat::UNSIGNED_INT8:					cMin = 0.0f;			cMax = 255.0f;			break;
		case TextureFormat::UNSIGNED_INT16:					cMin = 0.0f;			cMax = 65535.0f;		break;
		case TextureFormat::UNSIGNED_INT24:					cMin = 0.0f;			cMax = 16777215.0f;		break;
		case TextureFormat::UNSIGNED_INT32:					cMin = 0.0f;			cMax = 4294967040.f;	break; // Maximum exactly representable 32-bit integer: (2^24 - 1) * 2^8
		case TextureFormat::HALF_FLOAT:						cMin = -1e3f;			cMax = 1e3f;			break;
		case TextureFormat::FLOAT:							cMin = -1e5f;			cMax = 1e5f;			break;
		case TextureFormat::FLOAT64:						cMin = -1e5f;			cMax = 1e5f;			break;
		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:	cMin = 0.0f;			cMax = 1e4f;			break;
		case TextureFormat::UNSIGNED_INT_999_E5_REV:		cMin = 0.0f;			cMax = 1e5f;			break;
		case TextureFormat::UNSIGNED_BYTE_44:				cMin = 0.0f;			cMax = 15.f;			break;
		case TextureFormat::UNSIGNED_SHORT_4444:			cMin = 0.0f;			cMax = 15.f;			break;

		default:
			DE_ASSERT(false);
	}

	return Vec2(cMin, cMax);
}

/*--------------------------------------------------------------------*//*!
 * \brief Get standard parameters for testing texture format
 *
 * Returns TextureFormatInfo that describes good parameters for exercising
 * given TextureFormat. Parameters include value ranges per channel and
 * suitable lookup scaling and bias in order to reduce result back to
 * 0..1 range.
 *//*--------------------------------------------------------------------*/
TextureFormatInfo getTextureFormatInfo (const TextureFormat& format)
{
	// Special cases.
	if (format.type == TextureFormat::UNSIGNED_INT_1010102_REV)
		return TextureFormatInfo(Vec4(	     0.0f,		    0.0f,		    0.0f,		 0.0f),
								 Vec4(	  1023.0f,		 1023.0f,		 1023.0f,		 3.0f),
								 Vec4(1.0f/1023.f,	1.0f/1023.0f,	1.0f/1023.0f,	1.0f/3.0f),
								 Vec4(	     0.0f,		    0.0f,		    0.0f,		 0.0f));
	if (format.type == TextureFormat::SIGNED_INT_1010102_REV)
		return TextureFormatInfo(Vec4(	  -512.0f,		 -512.0f,		 -512.0f,		-2.0f),
								 Vec4(	   511.0f,		  511.0f,		  511.0f,		 1.0f),
								 Vec4(1.0f/1023.f,	1.0f/1023.0f,	1.0f/1023.0f,	1.0f/3.0f),
								 Vec4(	     0.5f,		    0.5f,		    0.5f,		 0.5f));
	else if (format.order == TextureFormat::D || format.order == TextureFormat::DS)
		return TextureFormatInfo(Vec4(0.0f,	0.0f,	0.0f,	0.0f),
								 Vec4(1.0f,	1.0f,	1.0f,	0.0f),
								 Vec4(1.0f,	1.0f,	1.0f,	1.0f),
								 Vec4(0.0f,	0.0f,	0.0f,	0.0f)); // Depth / stencil formats.
	else if (format == TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_SHORT_5551))
		return TextureFormatInfo(Vec4(0.0f, 0.0f, 0.0f, 0.5f),
								 Vec4(1.0f, 1.0f, 1.0f, 1.5f),
								 Vec4(1.0f, 1.0f, 1.0f, 1.0f),
								 Vec4(0.0f, 0.0f, 0.0f, 0.0f));
	else if (format.type == TextureFormat::UNSIGNED_SHORT_5551)
		return TextureFormatInfo(Vec4(	   0.0f,		  0.0f,		  0.0f,	0.0f),
								 Vec4(	  31.0f,		 31.0f,		 31.0f,	1.0f),
								 Vec4(1.0f/31.f,	1.0f/31.0f,	1.0f/31.0f,	1.0f),
								 Vec4(	   0.0f,		  0.0f,		  0.0f,	0.0f));
	else if (format.type == TextureFormat::UNSIGNED_SHORT_565)
		return TextureFormatInfo(Vec4(	   0.0f,		  0.0f,		  0.0f,	0.0f),
								 Vec4(	  31.0f,		 63.0f,		 31.0f,	0.0f),
								 Vec4(1.0f/31.f,	1.0f/63.0f,	1.0f/31.0f,	1.0f),
								 Vec4(	   0.0f,		  0.0f,		  0.0f,	0.0f));

	const Vec2						cRange		= getFloatChannelValueRange(format.type);
	const TextureSwizzle::Channel*	map			= getChannelReadSwizzle(format.order).components;
	const BVec4						chnMask		= BVec4(deInRange32(map[0], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
														deInRange32(map[1], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
														deInRange32(map[2], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
														deInRange32(map[3], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE);
	const float						scale		= 1.0f / (cRange[1] - cRange[0]);
	const float						bias		= -cRange[0] * scale;

	return TextureFormatInfo(select(cRange[0],	0.0f, chnMask),
							 select(cRange[1],	0.0f, chnMask),
							 select(scale,		1.0f, chnMask),
							 select(bias,		0.0f, chnMask));
}

IVec4 getFormatMinIntValue (const TextureFormat& format)
{
	DE_ASSERT(getTextureChannelClass(format.type) == TEXTURECHANNELCLASS_SIGNED_INTEGER);

	switch (format.type)
	{
		case TextureFormat::SIGNED_INT8:	return IVec4(std::numeric_limits<deInt8>::min());
		case TextureFormat::SIGNED_INT16:	return IVec4(std::numeric_limits<deInt16>::min());
		case TextureFormat::SIGNED_INT32:	return IVec4(std::numeric_limits<deInt32>::min());

		default:
			DE_FATAL("Invalid channel type");
			return IVec4(0);
	}
}

IVec4 getFormatMaxIntValue (const TextureFormat& format)
{
	DE_ASSERT(getTextureChannelClass(format.type) == TEXTURECHANNELCLASS_SIGNED_INTEGER);

	if (format == TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT_1010102_REV) ||
		format == TextureFormat(TextureFormat::BGRA, TextureFormat::SIGNED_INT_1010102_REV))
		return IVec4(511, 511, 511, 1);

	switch (format.type)
	{
		case TextureFormat::SIGNED_INT8:	return IVec4(std::numeric_limits<deInt8>::max());
		case TextureFormat::SIGNED_INT16:	return IVec4(std::numeric_limits<deInt16>::max());
		case TextureFormat::SIGNED_INT32:	return IVec4(std::numeric_limits<deInt32>::max());

		default:
			DE_FATAL("Invalid channel type");
			return IVec4(0);
	}
}

UVec4 getFormatMaxUintValue (const TextureFormat& format)
{
	DE_ASSERT(getTextureChannelClass(format.type) == TEXTURECHANNELCLASS_UNSIGNED_INTEGER);

	if (format == TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT_1010102_REV) ||
		format == TextureFormat(TextureFormat::BGRA, TextureFormat::UNSIGNED_INT_1010102_REV))
		return UVec4(1023u, 1023u, 1023u, 3u);

	switch (format.type)
	{
		case TextureFormat::UNSIGNED_INT8:	return UVec4(std::numeric_limits<deUint8>::max());
		case TextureFormat::UNSIGNED_INT16:	return UVec4(std::numeric_limits<deUint16>::max());
		case TextureFormat::UNSIGNED_INT24:	return UVec4(0xffffffu);
		case TextureFormat::UNSIGNED_INT32:	return UVec4(std::numeric_limits<deUint32>::max());

		default:
			DE_FATAL("Invalid channel type");
			return UVec4(0);
	}
}

static IVec4 getChannelBitDepth (TextureFormat::ChannelType channelType)
{
	// make sure this table is updated if format table is updated
	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40);

	switch (channelType)
	{
		case TextureFormat::SNORM_INT8:						return IVec4(8);
		case TextureFormat::SNORM_INT16:					return IVec4(16);
		case TextureFormat::SNORM_INT32:					return IVec4(32);
		case TextureFormat::UNORM_INT8:						return IVec4(8);
		case TextureFormat::UNORM_INT16:					return IVec4(16);
		case TextureFormat::UNORM_INT24:					return IVec4(24);
		case TextureFormat::UNORM_INT32:					return IVec4(32);
		case TextureFormat::UNORM_BYTE_44:					return IVec4(4,4,0,0);
		case TextureFormat::UNORM_SHORT_565:				return IVec4(5,6,5,0);
		case TextureFormat::UNORM_SHORT_4444:				return IVec4(4);
		case TextureFormat::UNORM_SHORT_555:				return IVec4(5,5,5,0);
		case TextureFormat::UNORM_SHORT_5551:				return IVec4(5,5,5,1);
		case TextureFormat::UNORM_SHORT_1555:				return IVec4(1,5,5,5);
		case TextureFormat::UNSIGNED_BYTE_44:				return IVec4(4,4,0,0);
		case TextureFormat::UNSIGNED_SHORT_565:				return IVec4(5,6,5,0);
		case TextureFormat::UNSIGNED_SHORT_4444:			return IVec4(4);
		case TextureFormat::UNSIGNED_SHORT_5551:			return IVec4(5,5,5,1);
		case TextureFormat::UNORM_INT_101010:				return IVec4(10,10,10,0);
		case TextureFormat::SNORM_INT_1010102_REV:			return IVec4(10,10,10,2);
		case TextureFormat::UNORM_INT_1010102_REV:			return IVec4(10,10,10,2);
		case TextureFormat::SIGNED_INT8:					return IVec4(8);
		case TextureFormat::SIGNED_INT16:					return IVec4(16);
		case TextureFormat::SIGNED_INT32:					return IVec4(32);
		case TextureFormat::UNSIGNED_INT8:					return IVec4(8);
		case TextureFormat::UNSIGNED_INT16:					return IVec4(16);
		case TextureFormat::UNSIGNED_INT24:					return IVec4(24);
		case TextureFormat::UNSIGNED_INT32:					return IVec4(32);
		case TextureFormat::SIGNED_INT_1010102_REV:			return IVec4(10,10,10,2);
		case TextureFormat::UNSIGNED_INT_1010102_REV:		return IVec4(10,10,10,2);
		case TextureFormat::UNSIGNED_INT_16_8_8:			return IVec4(16,8,0,0);
		case TextureFormat::UNSIGNED_INT_24_8:				return IVec4(24,8,0,0);
		case TextureFormat::UNSIGNED_INT_24_8_REV:			return IVec4(24,8,0,0);
		case TextureFormat::HALF_FLOAT:						return IVec4(16);
		case TextureFormat::FLOAT:							return IVec4(32);
		case TextureFormat::FLOAT64:						return IVec4(64);
		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:	return IVec4(11,11,10,0);
		case TextureFormat::UNSIGNED_INT_999_E5_REV:		return IVec4(9,9,9,0);
		case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:	return IVec4(32,8,0,0);
		case TextureFormat::UNORM_SHORT_10:					return IVec4(10);
		case TextureFormat::UNORM_SHORT_12:					return IVec4(12);
		default:
			DE_ASSERT(false);
			return IVec4(0);
	}
}

IVec4 getTextureFormatBitDepth (const TextureFormat& format)
{
	const IVec4						chnBits		= getChannelBitDepth(format.type);
	const TextureSwizzle::Channel*	map			= getChannelReadSwizzle(format.order).components;
	const BVec4						chnMask		= BVec4(deInRange32(map[0], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
														deInRange32(map[1], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
														deInRange32(map[2], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
														deInRange32(map[3], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE);
	const IVec4						chnSwz		= IVec4((chnMask[0]) ? ((int)map[0]) : (0),
														(chnMask[1]) ? ((int)map[1]) : (0),
														(chnMask[2]) ? ((int)map[2]) : (0),
														(chnMask[3]) ? ((int)map[3]) : (0));

	return select(chnBits.swizzle(chnSwz.x(), chnSwz.y(), chnSwz.z(), chnSwz.w()), IVec4(0), chnMask);
}

static IVec4 getChannelMantissaBitDepth (TextureFormat::ChannelType channelType)
{
	// make sure this table is updated if format table is updated
	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40);

	switch (channelType)
	{
		case TextureFormat::SNORM_INT8:
		case TextureFormat::SNORM_INT16:
		case TextureFormat::SNORM_INT32:
		case TextureFormat::UNORM_INT8:
		case TextureFormat::UNORM_INT16:
		case TextureFormat::UNORM_INT24:
		case TextureFormat::UNORM_INT32:
		case TextureFormat::UNORM_BYTE_44:
		case TextureFormat::UNORM_SHORT_565:
		case TextureFormat::UNORM_SHORT_4444:
		case TextureFormat::UNORM_SHORT_555:
		case TextureFormat::UNORM_SHORT_5551:
		case TextureFormat::UNORM_SHORT_1555:
		case TextureFormat::UNSIGNED_BYTE_44:
		case TextureFormat::UNSIGNED_SHORT_565:
		case TextureFormat::UNSIGNED_SHORT_4444:
		case TextureFormat::UNSIGNED_SHORT_5551:
		case TextureFormat::UNORM_INT_101010:
		case TextureFormat::SNORM_INT_1010102_REV:
		case TextureFormat::UNORM_INT_1010102_REV:
		case TextureFormat::SIGNED_INT8:
		case TextureFormat::SIGNED_INT16:
		case TextureFormat::SIGNED_INT32:
		case TextureFormat::UNSIGNED_INT8:
		case TextureFormat::UNSIGNED_INT16:
		case TextureFormat::UNSIGNED_INT24:
		case TextureFormat::UNSIGNED_INT32:
		case TextureFormat::SIGNED_INT_1010102_REV:
		case TextureFormat::UNSIGNED_INT_1010102_REV:
		case TextureFormat::UNSIGNED_INT_16_8_8:
		case TextureFormat::UNSIGNED_INT_24_8:
		case TextureFormat::UNSIGNED_INT_24_8_REV:
		case TextureFormat::UNSIGNED_INT_999_E5_REV:
		case TextureFormat::UNORM_SHORT_10:
		case TextureFormat::UNORM_SHORT_12:
			return getChannelBitDepth(channelType);

		case TextureFormat::HALF_FLOAT:						return IVec4(10);
		case TextureFormat::FLOAT:							return IVec4(23);
		case TextureFormat::FLOAT64:						return IVec4(52);
		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:	return IVec4(6,6,5,0);
		case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:	return IVec4(23,8,0,0);
		default:
			DE_ASSERT(false);
			return IVec4(0);
	}
}

IVec4 getTextureFormatMantissaBitDepth (const TextureFormat& format)
{
	const IVec4						chnBits		= getChannelMantissaBitDepth(format.type);
	const TextureSwizzle::Channel*	map			= getChannelReadSwizzle(format.order).components;
	const BVec4						chnMask		= BVec4(deInRange32(map[0], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
														deInRange32(map[1], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
														deInRange32(map[2], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
														deInRange32(map[3], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE);
	const IVec4						chnSwz		= IVec4((chnMask[0]) ? ((int)map[0]) : (0),
														(chnMask[1]) ? ((int)map[1]) : (0),
														(chnMask[2]) ? ((int)map[2]) : (0),
														(chnMask[3]) ? ((int)map[3]) : (0));

	return select(chnBits.swizzle(chnSwz.x(), chnSwz.y(), chnSwz.z(), chnSwz.w()), IVec4(0), chnMask);
}

BVec4 getTextureFormatChannelMask (const TextureFormat& format)
{
	const TextureSwizzle::Channel* const map = getChannelReadSwizzle(format.order).components;
	return BVec4(deInRange32(map[0], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
				 deInRange32(map[1], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
				 deInRange32(map[2], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
				 deInRange32(map[3], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE);
}

static inline float linearInterpolate (float t, float minVal, float maxVal)
{
	return minVal + (maxVal - minVal) * t;
}

static inline Vec4 linearInterpolate (float t, const Vec4& a, const Vec4& b)
{
	return a + (b - a) * t;
}

enum
{
	CLEAR_OPTIMIZE_THRESHOLD		= 128,
	CLEAR_OPTIMIZE_MAX_PIXEL_SIZE	= 8
};

inline void fillRow (const PixelBufferAccess& dst, int y, int z, int pixelSize, const deUint8* pixel)
{
	DE_ASSERT(dst.getPixelPitch() == pixelSize); // only tightly packed

	deUint8*	dstPtr	= (deUint8*)dst.getPixelPtr(0, y, z);
	int			width	= dst.getWidth();

	if (pixelSize == 8 && deIsAlignedPtr(dstPtr, pixelSize))
	{
		deUint64 val;
		memcpy(&val, pixel, sizeof(val));

		for (int i = 0; i < width; i++)
			((deUint64*)dstPtr)[i] = val;
	}
	else if (pixelSize == 4 && deIsAlignedPtr(dstPtr, pixelSize))
	{
		deUint32 val;
		memcpy(&val, pixel, sizeof(val));

		for (int i = 0; i < width; i++)
			((deUint32*)dstPtr)[i] = val;
	}
	else
	{
		for (int i = 0; i < width; i++)
			for (int j = 0; j < pixelSize; j++)
				dstPtr[i*pixelSize+j] = pixel[j];
	}
}

void clear (const PixelBufferAccess& access, const Vec4& color)
{
	const int	pixelSize				= access.getFormat().getPixelSize();
	const int	pixelPitch				= access.getPixelPitch();
	const bool	rowPixelsTightlyPacked	= (pixelSize == pixelPitch);

	if (access.getWidth()*access.getHeight()*access.getDepth() >= CLEAR_OPTIMIZE_THRESHOLD &&
		pixelSize < CLEAR_OPTIMIZE_MAX_PIXEL_SIZE && rowPixelsTightlyPacked)
	{
		// Convert to destination format.
		union
		{
			deUint8		u8[CLEAR_OPTIMIZE_MAX_PIXEL_SIZE];
			deUint64	u64; // Forces 64-bit alignment.
		} pixel;
		DE_STATIC_ASSERT(sizeof(pixel) == CLEAR_OPTIMIZE_MAX_PIXEL_SIZE);
		PixelBufferAccess(access.getFormat(), 1, 1, 1, 0, 0, &pixel.u8[0]).setPixel(color, 0, 0);

		for (int z = 0; z < access.getDepth(); z++)
			for (int y = 0; y < access.getHeight(); y++)
				fillRow(access, y, z, pixelSize, &pixel.u8[0]);
	}
	else
	{
		for (int z = 0; z < access.getDepth(); z++)
			for (int y = 0; y < access.getHeight(); y++)
				for (int x = 0; x < access.getWidth(); x++)
					access.setPixel(color, x, y, z);
	}
}

void clear (const PixelBufferAccess& access, const IVec4& color)
{
	const int	pixelSize				= access.getFormat().getPixelSize();
	const int	pixelPitch				= access.getPixelPitch();
	const bool	rowPixelsTightlyPacked	= (pixelSize == pixelPitch);

	if (access.getWidth()*access.getHeight()*access.getDepth() >= CLEAR_OPTIMIZE_THRESHOLD &&
		pixelSize < CLEAR_OPTIMIZE_MAX_PIXEL_SIZE && rowPixelsTightlyPacked)
	{
		// Convert to destination format.
		union
		{
			deUint8		u8[CLEAR_OPTIMIZE_MAX_PIXEL_SIZE];
			deUint64	u64; // Forces 64-bit alignment.
		} pixel;
		DE_STATIC_ASSERT(sizeof(pixel) == CLEAR_OPTIMIZE_MAX_PIXEL_SIZE);
		PixelBufferAccess(access.getFormat(), 1, 1, 1, 0, 0, &pixel.u8[0]).setPixel(color, 0, 0);

		for (int z = 0; z < access.getDepth(); z++)
			for (int y = 0; y < access.getHeight(); y++)
				fillRow(access, y, z, pixelSize, &pixel.u8[0]);
	}
	else
	{
		for (int z = 0; z < access.getDepth(); z++)
			for (int y = 0; y < access.getHeight(); y++)
				for (int x = 0; x < access.getWidth(); x++)
					access.setPixel(color, x, y, z);
	}
}

void clear (const PixelBufferAccess& access, const UVec4& color)
{
	clear(access, color.cast<deInt32>());
}

void clearDepth (const PixelBufferAccess& access, float depth)
{
	DE_ASSERT(access.getFormat().order == TextureFormat::DS || access.getFormat().order == TextureFormat::D);

	clear(getEffectiveDepthStencilAccess(access, Sampler::MODE_DEPTH), tcu::Vec4(depth, 0.0f, 0.0f, 0.0f));
}

void clearStencil (const PixelBufferAccess& access, int stencil)
{
	DE_ASSERT(access.getFormat().order == TextureFormat::DS || access.getFormat().order == TextureFormat::S);

	clear(getEffectiveDepthStencilAccess(access, Sampler::MODE_STENCIL), tcu::UVec4(stencil, 0u, 0u, 0u));
}

static void fillWithComponentGradients1D (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal)
{
	DE_ASSERT(access.getHeight() == 1);
	for (int x = 0; x < access.getWidth(); x++)
	{
		float s = ((float)x + 0.5f) / (float)access.getWidth();

		float r = linearInterpolate(s, minVal.x(), maxVal.x());
		float g = linearInterpolate(s, minVal.y(), maxVal.y());
		float b = linearInterpolate(s, minVal.z(), maxVal.z());
		float a = linearInterpolate(s, minVal.w(), maxVal.w());

		access.setPixel(tcu::Vec4(r, g, b, a), x, 0);
	}
}

static void fillWithComponentGradients2D (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal)
{
	for (int y = 0; y < access.getHeight(); y++)
	{
		for (int x = 0; x < access.getWidth(); x++)
		{
			float s = ((float)x + 0.5f) / (float)access.getWidth();
			float t = ((float)y + 0.5f) / (float)access.getHeight();

			float r = linearInterpolate((      s  +       t) *0.5f, minVal.x(), maxVal.x());
			float g = linearInterpolate((      s  + (1.0f-t))*0.5f, minVal.y(), maxVal.y());
			float b = linearInterpolate(((1.0f-s) +       t) *0.5f, minVal.z(), maxVal.z());
			float a = linearInterpolate(((1.0f-s) + (1.0f-t))*0.5f, minVal.w(), maxVal.w());

			access.setPixel(tcu::Vec4(r, g, b, a), x, y);
		}
	}
}

static void fillWithComponentGradients3D (const PixelBufferAccess& dst, const Vec4& minVal, const Vec4& maxVal)
{
	for (int z = 0; z < dst.getDepth(); z++)
	{
		for (int y = 0; y < dst.getHeight(); y++)
		{
			for (int x = 0; x < dst.getWidth(); x++)
			{
				float s = ((float)x + 0.5f) / (float)dst.getWidth();
				float t = ((float)y + 0.5f) / (float)dst.getHeight();
				float p = ((float)z + 0.5f) / (float)dst.getDepth();

				float r = linearInterpolate(s,						minVal.x(), maxVal.x());
				float g = linearInterpolate(t,						minVal.y(), maxVal.y());
				float b = linearInterpolate(p,						minVal.z(), maxVal.z());
				float a = linearInterpolate(1.0f - (s+t+p)/3.0f,	minVal.w(), maxVal.w());

				dst.setPixel(tcu::Vec4(r, g, b, a), x, y, z);
			}
		}
	}
}

void fillWithComponentGradients (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal)
{
	if (isCombinedDepthStencilType(access.getFormat().type))
	{
		const bool hasDepth		= access.getFormat().order == tcu::TextureFormat::DS || access.getFormat().order == tcu::TextureFormat::D;
		const bool hasStencil	= access.getFormat().order == tcu::TextureFormat::DS || access.getFormat().order == tcu::TextureFormat::S;

		DE_ASSERT(hasDepth || hasStencil);

		// For combined formats, treat D and S as separate channels
		if (hasDepth)
			fillWithComponentGradients(getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_DEPTH), minVal, maxVal);
		if (hasStencil)
			fillWithComponentGradients(getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_STENCIL), minVal.swizzle(3,2,1,0), maxVal.swizzle(3,2,1,0));
	}
	else
	{
		if (access.getHeight() == 1 && access.getDepth() == 1)
			fillWithComponentGradients1D(access, minVal, maxVal);
		else if (access.getDepth() == 1)
			fillWithComponentGradients2D(access, minVal, maxVal);
		else
			fillWithComponentGradients3D(access, minVal, maxVal);
	}
}

static void fillWithGrid1D (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB)
{
	for (int x = 0; x < access.getWidth(); x++)
	{
		int mx = (x / cellSize) % 2;

		if (mx)
			access.setPixel(colorB, x, 0);
		else
			access.setPixel(colorA, x, 0);
	}
}

static void fillWithGrid2D (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB)
{
	for (int y = 0; y < access.getHeight(); y++)
	{
		for (int x = 0; x < access.getWidth(); x++)
		{
			int mx = (x / cellSize) % 2;
			int my = (y / cellSize) % 2;

			if (mx ^ my)
				access.setPixel(colorB, x, y);
			else
				access.setPixel(colorA, x, y);
		}
	}
}

static void fillWithGrid3D (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB)
{
	for (int z = 0; z < access.getDepth(); z++)
	{
		for (int y = 0; y < access.getHeight(); y++)
		{
			for (int x = 0; x < access.getWidth(); x++)
			{
				int mx = (x / cellSize) % 2;
				int my = (y / cellSize) % 2;
				int mz = (z / cellSize) % 2;

				if (mx ^ my ^ mz)
					access.setPixel(colorB, x, y, z);
				else
					access.setPixel(colorA, x, y, z);
			}
		}
	}
}

void fillWithGrid (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB)
{
	if (isCombinedDepthStencilType(access.getFormat().type))
	{
		const bool hasDepth		= access.getFormat().order == tcu::TextureFormat::DS || access.getFormat().order == tcu::TextureFormat::D;
		const bool hasStencil	= access.getFormat().order == tcu::TextureFormat::DS || access.getFormat().order == tcu::TextureFormat::S;

		DE_ASSERT(hasDepth || hasStencil);

		// For combined formats, treat D and S as separate channels
		if (hasDepth)
			fillWithGrid(getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_DEPTH), cellSize, colorA, colorB);
		if (hasStencil)
			fillWithGrid(getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_STENCIL), cellSize, colorA.swizzle(3,2,1,0), colorB.swizzle(3,2,1,0));
	}
	else
	{
		if (access.getHeight() == 1 && access.getDepth() == 1)
			fillWithGrid1D(access, cellSize, colorA, colorB);
		else if (access.getDepth() == 1)
			fillWithGrid2D(access, cellSize, colorA, colorB);
		else
			fillWithGrid3D(access, cellSize, colorA, colorB);
	}
}

void fillWithRepeatableGradient (const PixelBufferAccess& access, const Vec4& colorA, const Vec4& colorB)
{
	for (int y = 0; y < access.getHeight(); y++)
	{
		for (int x = 0; x < access.getWidth(); x++)
		{
			float s = ((float)x + 0.5f) / (float)access.getWidth();
			float t = ((float)y + 0.5f) / (float)access.getHeight();

			float a = s > 0.5f ? (2.0f - 2.0f*s) : 2.0f*s;
			float b = t > 0.5f ? (2.0f - 2.0f*t) : 2.0f*t;

			float p = deFloatClamp(deFloatSqrt(a*a + b*b), 0.0f, 1.0f);
			access.setPixel(linearInterpolate(p, colorA, colorB), x, y);
		}
	}
}

void fillWithRGBAQuads (const PixelBufferAccess& dst)
{
	TCU_CHECK_INTERNAL(dst.getDepth() == 1);
	int width	= dst.getWidth();
	int height	= dst.getHeight();
	int	left	= width/2;
	int top		= height/2;

	clear(getSubregion(dst, 0,		0,		0, left,		top,		1),	Vec4(1.0f, 0.0f, 0.0f, 1.0f));
	clear(getSubregion(dst, left,	0,		0, width-left,	top,		1),	Vec4(0.0f, 1.0f, 0.0f, 1.0f));
	clear(getSubregion(dst, 0,		top,	0, left,		height-top,	1), Vec4(0.0f, 0.0f, 1.0f, 0.0f));
	clear(getSubregion(dst, left,	top,	0, width-left,	height-top, 1), Vec4(0.5f, 0.5f, 0.5f, 1.0f));
}

// \todo [2012-11-13 pyry] There is much better metaballs code in CL SIR value generators.
void fillWithMetaballs (const PixelBufferAccess& dst, int numBalls, deUint32 seed)
{
	TCU_CHECK_INTERNAL(dst.getDepth() == 1);
	std::vector<Vec2>	points(numBalls);
	de::Random			rnd(seed);

	for (int i = 0; i < numBalls; i++)
	{
		float x = rnd.getFloat();
		float y = rnd.getFloat();
		points[i] = (Vec2(x, y));
	}

	for (int y = 0; y < dst.getHeight(); y++)
	for (int x = 0; x < dst.getWidth(); x++)
	{
		Vec2 p((float)x/(float)dst.getWidth(), (float)y/(float)dst.getHeight());

		float sum = 0.0f;
		for (std::vector<Vec2>::const_iterator i = points.begin(); i != points.end(); i++)
		{
			Vec2	d = p - *i;
			float	f = 0.01f / (d.x()*d.x() + d.y()*d.y());

			sum += f;
		}

		dst.setPixel(Vec4(sum), x, y);
	}
}

void copy (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src)
{
	DE_ASSERT(src.getSize() == dst.getSize());

	const int	width				= dst.getWidth();
	const int	height				= dst.getHeight();
	const int	depth				= dst.getDepth();

	const int	srcPixelSize		= src.getFormat().getPixelSize();
	const int	dstPixelSize		= dst.getFormat().getPixelSize();
	const int	srcPixelPitch		= src.getPixelPitch();
	const int	dstPixelPitch		= dst.getPixelPitch();
	const bool	srcTightlyPacked	= (srcPixelSize == srcPixelPitch);
	const bool	dstTightlyPacked	= (dstPixelSize == dstPixelPitch);

	const bool	srcHasDepth			= (src.getFormat().order == tcu::TextureFormat::DS || src.getFormat().order == tcu::TextureFormat::D);
	const bool	srcHasStencil		= (src.getFormat().order == tcu::TextureFormat::DS || src.getFormat().order == tcu::TextureFormat::S);
	const bool	dstHasDepth			= (dst.getFormat().order == tcu::TextureFormat::DS || dst.getFormat().order == tcu::TextureFormat::D);
	const bool	dstHasStencil		= (dst.getFormat().order == tcu::TextureFormat::DS || dst.getFormat().order == tcu::TextureFormat::S);

	if (src.getFormat() == dst.getFormat() && srcTightlyPacked && dstTightlyPacked)
	{
		// Fast-path for matching formats.
		for (int z = 0; z < depth; z++)
		for (int y = 0; y < height; y++)
			deMemcpy(dst.getPixelPtr(0, y, z), src.getPixelPtr(0, y, z), srcPixelSize*width);
	}
	else if (src.getFormat() == dst.getFormat())
	{
		// Bit-exact copy for matching formats.
		for (int z = 0; z < depth; z++)
		for (int y = 0; y < height; y++)
		for (int x = 0; x < width; x++)
			deMemcpy(dst.getPixelPtr(x, y, z), src.getPixelPtr(x, y, z), srcPixelSize);
	}
	else if (srcHasDepth || srcHasStencil || dstHasDepth || dstHasStencil)
	{
		DE_ASSERT((srcHasDepth && dstHasDepth) || (srcHasStencil && dstHasStencil)); // must have at least one common channel

		if (dstHasDepth && srcHasDepth)
		{
			for (int z = 0; z < depth; z++)
			for (int y = 0; y < height; y++)
			for (int x = 0; x < width; x++)
				dst.setPixDepth(src.getPixDepth(x, y, z), x, y, z);
		}
		else if (dstHasDepth && !srcHasDepth)
		{
			// consistency with color copies
			tcu::clearDepth(dst, 0.0f);
		}

		if (dstHasStencil && srcHasStencil)
		{
			for (int z = 0; z < depth; z++)
			for (int y = 0; y < height; y++)
			for (int x = 0; x < width; x++)
				dst.setPixStencil(src.getPixStencil(x, y, z), x, y, z);
		}
		else if (dstHasStencil && !srcHasStencil)
		{
			// consistency with color copies
			tcu::clearStencil(dst, 0u);
		}
	}
	else
	{
		TextureChannelClass		srcClass	= getTextureChannelClass(src.getFormat().type);
		TextureChannelClass		dstClass	= getTextureChannelClass(dst.getFormat().type);
		bool					srcIsInt	= srcClass == TEXTURECHANNELCLASS_SIGNED_INTEGER || srcClass == TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
		bool					dstIsInt	= dstClass == TEXTURECHANNELCLASS_SIGNED_INTEGER || dstClass == TEXTURECHANNELCLASS_UNSIGNED_INTEGER;

		if (srcIsInt && dstIsInt)
		{
			for (int z = 0; z < depth; z++)
			for (int y = 0; y < height; y++)
			for (int x = 0; x < width; x++)
				dst.setPixel(src.getPixelInt(x, y, z), x, y, z);
		}
		else
		{
			for (int z = 0; z < depth; z++)
			for (int y = 0; y < height; y++)
			for (int x = 0; x < width; x++)
				dst.setPixel(src.getPixel(x, y, z), x, y, z);
		}
	}
}

void scale (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src, Sampler::FilterMode filter)
{
	DE_ASSERT(filter == Sampler::NEAREST || filter == Sampler::LINEAR);

	Sampler sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE,
					filter, filter, 0.0f, false);

	float sX = (float)src.getWidth() / (float)dst.getWidth();
	float sY = (float)src.getHeight() / (float)dst.getHeight();
	float sZ = (float)src.getDepth() / (float)dst.getDepth();

	if (dst.getDepth() == 1 && src.getDepth() == 1)
	{
		for (int y = 0; y < dst.getHeight(); y++)
		for (int x = 0; x < dst.getWidth(); x++)
			dst.setPixel(linearToSRGBIfNeeded(dst.getFormat(), src.sample2D(sampler, filter, ((float)x+0.5f)*sX, ((float)y+0.5f)*sY, 0)), x, y);
	}
	else
	{
		for (int z = 0; z < dst.getDepth(); z++)
		for (int y = 0; y < dst.getHeight(); y++)
		for (int x = 0; x < dst.getWidth(); x++)
			dst.setPixel(linearToSRGBIfNeeded(dst.getFormat(), src.sample3D(sampler, filter, ((float)x+0.5f)*sX, ((float)y+0.5f)*sY, ((float)z+0.5f)*sZ)), x, y, z);
	}
}

void estimatePixelValueRange (const ConstPixelBufferAccess& access, Vec4& minVal, Vec4& maxVal)
{
	const TextureFormat& format = access.getFormat();

	switch (getTextureChannelClass(format.type))
	{
		case TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
			// Normalized unsigned formats.
			minVal = Vec4(0.0f);
			maxVal = Vec4(1.0f);
			break;

		case TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
			// Normalized signed formats.
			minVal = Vec4(-1.0f);
			maxVal = Vec4(+1.0f);
			break;

		default:
			// \note Samples every 4/8th pixel.
			minVal = Vec4(std::numeric_limits<float>::max());
			maxVal = Vec4(std::numeric_limits<float>::min());

			for (int z = 0; z < access.getDepth(); z += 2)
			{
				for (int y = 0; y < access.getHeight(); y += 2)
				{
					for (int x = 0; x < access.getWidth(); x += 2)
					{
						Vec4 p = access.getPixel(x, y, z);

						minVal[0] = (deFloatIsNaN(p[0]) ? minVal[0] : de::min(minVal[0], p[0]));
						minVal[1] = (deFloatIsNaN(p[1]) ? minVal[1] : de::min(minVal[1], p[1]));
						minVal[2] = (deFloatIsNaN(p[2]) ? minVal[2] : de::min(minVal[2], p[2]));
						minVal[3] = (deFloatIsNaN(p[3]) ? minVal[3] : de::min(minVal[3], p[3]));

						maxVal[0] = (deFloatIsNaN(p[0]) ? maxVal[0] : de::max(maxVal[0], p[0]));
						maxVal[1] = (deFloatIsNaN(p[1]) ? maxVal[1] : de::max(maxVal[1], p[1]));
						maxVal[2] = (deFloatIsNaN(p[2]) ? maxVal[2] : de::max(maxVal[2], p[2]));
						maxVal[3] = (deFloatIsNaN(p[3]) ? maxVal[3] : de::max(maxVal[3], p[3]));
					}
				}
			}
			break;
	}
}

void computePixelScaleBias (const ConstPixelBufferAccess& access, Vec4& scale, Vec4& bias)
{
	Vec4 minVal, maxVal;
	estimatePixelValueRange(access, minVal, maxVal);

	const float eps = 0.0001f;

	for (int c = 0; c < 4; c++)
	{
		if (maxVal[c] - minVal[c] < eps)
		{
			scale[c]	= (maxVal[c] < eps) ? 1.0f : (1.0f / maxVal[c]);
			bias[c]		= (c == 3) ? (1.0f - maxVal[c]*scale[c]) : (0.0f - minVal[c]*scale[c]);
		}
		else
		{
			scale[c]	= 1.0f / (maxVal[c] - minVal[c]);
			bias[c]		= 0.0f - minVal[c]*scale[c];
		}
	}
}

int getCubeArrayFaceIndex (CubeFace face)
{
	DE_ASSERT((int)face >= 0 && face < CUBEFACE_LAST);

	switch (face)
	{
		case CUBEFACE_POSITIVE_X:	return 0;
		case CUBEFACE_NEGATIVE_X:	return 1;
		case CUBEFACE_POSITIVE_Y:	return 2;
		case CUBEFACE_NEGATIVE_Y:	return 3;
		case CUBEFACE_POSITIVE_Z:	return 4;
		case CUBEFACE_NEGATIVE_Z:	return 5;

		default:
			return -1;
	}
}

deUint32 packRGB999E5 (const tcu::Vec4& color)
{
	const int	mBits	= 9;
	const int	eBits	= 5;
	const int	eBias	= 15;
	const int	eMax	= (1<<eBits)-1;
	const float	maxVal	= (float)(((1<<mBits) - 1) * (1<<(eMax-eBias))) / (float)(1<<mBits);

	float	rc		= deFloatClamp(color[0], 0.0f, maxVal);
	float	gc		= deFloatClamp(color[1], 0.0f, maxVal);
	float	bc		= deFloatClamp(color[2], 0.0f, maxVal);
	float	maxc	= de::max(rc, de::max(gc, bc));
	int		exps	= de::max(-eBias - 1, deFloorFloatToInt32(deFloatLog2(maxc))) + 1 + eBias;
	float	e		= deFloatPow(2.0f, (float)(exps-eBias-mBits));
	int		maxs	= deFloorFloatToInt32(maxc / e + 0.5f);

	if (maxs == (1<<mBits))
	{
		exps++;
		e *= 2.0f;
	}

	deUint32 rs = (deUint32)deFloorFloatToInt32(rc / e + 0.5f);
	deUint32 gs = (deUint32)deFloorFloatToInt32(gc / e + 0.5f);
	deUint32 bs = (deUint32)deFloorFloatToInt32(bc / e + 0.5f);

	DE_ASSERT((exps & ~((1<<5)-1)) == 0);
	DE_ASSERT((rs & ~((1<<9)-1)) == 0);
	DE_ASSERT((gs & ~((1<<9)-1)) == 0);
	DE_ASSERT((bs & ~((1<<9)-1)) == 0);

	return rs | (gs << 9) | (bs << 18) | (exps << 27);
}

// Sampler utils

static const void* addOffset (const void* ptr, int numBytes)
{
	return (const deUint8*)ptr + numBytes;
}

static void* addOffset (void* ptr, int numBytes)
{
	return (deUint8*)ptr + numBytes;
}

template <typename AccessType>
static AccessType toSamplerAccess (const AccessType& baseAccess, Sampler::DepthStencilMode mode)
{
	// make sure to update this if type table is updated
	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40);

	if (!isCombinedDepthStencilType(baseAccess.getFormat().type))
		return baseAccess;
	else
	{
#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
		const deUint32 uint32ByteOffsetBits0To8		= 0; //!< least significant byte in the lowest address
		const deUint32 uint32ByteOffsetBits0To24	= 0;
		const deUint32 uint32ByteOffsetBits8To32	= 1;
		const deUint32 uint32ByteOffsetBits16To32	= 2;
		const deUint32 uint32ByteOffsetBits24To32	= 3;
#else
		const deUint32 uint32ByteOffsetBits0To8		= 3; //!< least significant byte in the highest address
		const deUint32 uint32ByteOffsetBits0To24	= 1;
		const deUint32 uint32ByteOffsetBits8To32	= 0;
		const deUint32 uint32ByteOffsetBits16To32	= 0;
		const deUint32 uint32ByteOffsetBits24To32	= 0;
#endif

		// Sampled channel must exist
		DE_ASSERT(baseAccess.getFormat().order == TextureFormat::DS ||
				  (mode == Sampler::MODE_DEPTH && baseAccess.getFormat().order == TextureFormat::D) ||
				  (mode == Sampler::MODE_STENCIL && baseAccess.getFormat().order == TextureFormat::S));

		// combined formats have multiple channel classes, detect on sampler settings
		switch (baseAccess.getFormat().type)
		{
			case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
			{
				if (mode == Sampler::MODE_DEPTH)
				{
					// select the float component
					return AccessType(TextureFormat(TextureFormat::D, TextureFormat::FLOAT),
									  baseAccess.getSize(),
									  baseAccess.getPitch(),
									  baseAccess.getDataPtr());
				}
				else if (mode == Sampler::MODE_STENCIL)
				{
					// select the uint 8 component
					return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8),
									  baseAccess.getSize(),
									  baseAccess.getPitch(),
									  addOffset(baseAccess.getDataPtr(), 4 + uint32ByteOffsetBits0To8));
				}
				else
				{
					// unknown sampler mode
					DE_ASSERT(false);
					return AccessType();
				}
			}

			case TextureFormat::UNSIGNED_INT_16_8_8:
			{
				if (mode == Sampler::MODE_DEPTH)
				{
					// select the unorm16 component
					return AccessType(TextureFormat(TextureFormat::D, TextureFormat::UNORM_INT16),
									  baseAccess.getSize(),
									  baseAccess.getPitch(),
									  addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits16To32));
				}
				else if (mode == Sampler::MODE_STENCIL)
				{
					// select the uint 8 component
					return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8),
									  baseAccess.getSize(),
									  baseAccess.getPitch(),
									  addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits0To8));
				}
				else
				{
					// unknown sampler mode
					DE_ASSERT(false);
					return AccessType();
				}
			}

			case TextureFormat::UNSIGNED_INT_24_8:
			{
				if (mode == Sampler::MODE_DEPTH)
				{
					// select the unorm24 component
					return AccessType(TextureFormat(TextureFormat::D, TextureFormat::UNORM_INT24),
									  baseAccess.getSize(),
									  baseAccess.getPitch(),
									  addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits8To32));
				}
				else if (mode == Sampler::MODE_STENCIL)
				{
					// select the uint 8 component
					return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8),
									  baseAccess.getSize(),
									  baseAccess.getPitch(),
									  addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits0To8));
				}
				else
				{
					// unknown sampler mode
					DE_ASSERT(false);
					return AccessType();
				}
			}

			case TextureFormat::UNSIGNED_INT_24_8_REV:
			{
				if (mode == Sampler::MODE_DEPTH)
				{
					// select the unorm24 component
					return AccessType(TextureFormat(TextureFormat::D, TextureFormat::UNORM_INT24),
									  baseAccess.getSize(),
									  baseAccess.getPitch(),
									  addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits0To24));
				}
				else if (mode == Sampler::MODE_STENCIL)
				{
					// select the uint 8 component
					return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8),
									  baseAccess.getSize(),
									  baseAccess.getPitch(),
									  addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits24To32));
				}
				else
				{
					// unknown sampler mode
					DE_ASSERT(false);
					return AccessType();
				}
			}

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

PixelBufferAccess getEffectiveDepthStencilAccess (const PixelBufferAccess& baseAccess, Sampler::DepthStencilMode mode)
{
	return toSamplerAccess<PixelBufferAccess>(baseAccess, mode);
}

ConstPixelBufferAccess getEffectiveDepthStencilAccess (const ConstPixelBufferAccess& baseAccess, Sampler::DepthStencilMode mode)
{
	return toSamplerAccess<ConstPixelBufferAccess>(baseAccess, mode);
}

TextureFormat getEffectiveDepthStencilTextureFormat (const TextureFormat& baseFormat, Sampler::DepthStencilMode mode)
{
	return toSamplerAccess(ConstPixelBufferAccess(baseFormat, IVec3(0, 0, 0), DE_NULL), mode).getFormat();
}

template <typename ViewType>
ViewType getEffectiveTView (const ViewType& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
{
	storage.resize(src.getNumLevels());

	ViewType view = ViewType(src.getNumLevels(), &storage[0]);

	for (int levelNdx = 0; levelNdx < src.getNumLevels(); ++levelNdx)
		storage[levelNdx] = tcu::getEffectiveDepthStencilAccess(src.getLevel(levelNdx), sampler.depthStencilMode);

	return view;
}

tcu::TextureCubeView getEffectiveTView (const tcu::TextureCubeView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
{
	storage.resize(tcu::CUBEFACE_LAST * src.getNumLevels());

	const tcu::ConstPixelBufferAccess* storagePtrs[tcu::CUBEFACE_LAST] =
	{
		&storage[0 * src.getNumLevels()],
		&storage[1 * src.getNumLevels()],
		&storage[2 * src.getNumLevels()],
		&storage[3 * src.getNumLevels()],
		&storage[4 * src.getNumLevels()],
		&storage[5 * src.getNumLevels()],
	};

	tcu::TextureCubeView view = tcu::TextureCubeView(src.getNumLevels(), storagePtrs);

	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
	for (int levelNdx = 0; levelNdx < src.getNumLevels(); ++levelNdx)
		storage[faceNdx * src.getNumLevels() + levelNdx] = tcu::getEffectiveDepthStencilAccess(src.getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), sampler.depthStencilMode);

	return view;
}

tcu::Texture1DView getEffectiveTextureView (const tcu::Texture1DView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
{
	return getEffectiveTView(src, storage, sampler);
}

tcu::Texture2DView getEffectiveTextureView (const tcu::Texture2DView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
{
	return getEffectiveTView(src, storage, sampler);
}

tcu::Texture3DView getEffectiveTextureView (const tcu::Texture3DView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
{
	return getEffectiveTView(src, storage, sampler);
}

tcu::Texture1DArrayView getEffectiveTextureView (const tcu::Texture1DArrayView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
{
	return getEffectiveTView(src, storage, sampler);
}

tcu::Texture2DArrayView getEffectiveTextureView (const tcu::Texture2DArrayView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
{
	return getEffectiveTView(src, storage, sampler);
}

tcu::TextureCubeView getEffectiveTextureView (const tcu::TextureCubeView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
{
	return getEffectiveTView(src, storage, sampler);
}

tcu::TextureCubeArrayView getEffectiveTextureView (const tcu::TextureCubeArrayView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
{
	return getEffectiveTView(src, storage, sampler);
}

//! Returns the effective swizzle of a border color. The effective swizzle is the
//! equal to first writing an RGBA color with a write swizzle and then reading
//! it back using a read swizzle, i.e. BorderSwizzle(c) == readSwizzle(writeSwizzle(C))
static const TextureSwizzle& getBorderColorReadSwizzle (TextureFormat::ChannelOrder order)
{
	// make sure to update these tables when channel orders are updated
	DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 21);

	static const TextureSwizzle INV		= {{ TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ONE	}};
	static const TextureSwizzle R		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ONE	}};
	static const TextureSwizzle A		= {{ TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_3	}};
	static const TextureSwizzle I		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0	}};
	static const TextureSwizzle L		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_ONE	}};
	static const TextureSwizzle LA		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_3	}};
	static const TextureSwizzle RG		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ONE	}};
	static const TextureSwizzle RA		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_3	}};
	static const TextureSwizzle RGB		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_2,		TextureSwizzle::CHANNEL_ONE	}};
	static const TextureSwizzle RGBA	= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_2,		TextureSwizzle::CHANNEL_3	}};
	static const TextureSwizzle D		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ONE	}};
	static const TextureSwizzle S		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ONE	}};

	const TextureSwizzle* swizzle;

	switch (order)
	{
		case TextureFormat::R:			swizzle = &R;		break;
		case TextureFormat::A:			swizzle = &A;		break;
		case TextureFormat::I:			swizzle = &I;		break;
		case TextureFormat::L:			swizzle = &L;		break;
		case TextureFormat::LA:			swizzle = &LA;		break;
		case TextureFormat::RG:			swizzle = &RG;		break;
		case TextureFormat::RA:			swizzle = &RA;		break;
		case TextureFormat::RGB:		swizzle = &RGB;		break;
		case TextureFormat::RGBA:		swizzle = &RGBA;	break;
		case TextureFormat::ARGB:		swizzle = &RGBA;	break;
		case TextureFormat::BGR:		swizzle = &RGB;		break;
		case TextureFormat::BGRA:		swizzle = &RGBA;	break;
		case TextureFormat::sR:			swizzle = &R;		break;
		case TextureFormat::sRG:		swizzle = &RG;		break;
		case TextureFormat::sRGB:		swizzle = &RGB;		break;
		case TextureFormat::sRGBA:		swizzle = &RGBA;	break;
		case TextureFormat::sBGR:		swizzle = &RGB;		break;
		case TextureFormat::sBGRA:		swizzle = &RGBA;	break;
		case TextureFormat::D:			swizzle = &D;		break;
		case TextureFormat::S:			swizzle = &S;		break;

		case TextureFormat::DS:
			DE_ASSERT(false); // combined depth-stencil border color?
			swizzle = &INV;
			break;

		default:
			DE_ASSERT(false);
			swizzle = &INV;
			break;
	}

#ifdef DE_DEBUG

	{
		// check that BorderSwizzle(c) == readSwizzle(writeSwizzle(C))
		const TextureSwizzle& readSwizzle	= getChannelReadSwizzle(order);
		const TextureSwizzle& writeSwizzle	= getChannelWriteSwizzle(order);

		for (int ndx = 0; ndx < 4; ++ndx)
		{
			TextureSwizzle::Channel writeRead = readSwizzle.components[ndx];
			if (deInRange32(writeRead, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE)
				writeRead = writeSwizzle.components[(int)writeRead];
			DE_ASSERT(writeRead == swizzle->components[ndx]);
		}
	}

#endif

	return *swizzle;
}

static tcu::UVec4 getNBitUnsignedIntegerVec4MaxValue (const tcu::IVec4& numBits)
{
	return tcu::UVec4((numBits[0] > 0) ? (deUintMaxValue32(numBits[0])) : (0),
					  (numBits[1] > 0) ? (deUintMaxValue32(numBits[1])) : (0),
					  (numBits[2] > 0) ? (deUintMaxValue32(numBits[2])) : (0),
					  (numBits[3] > 0) ? (deUintMaxValue32(numBits[3])) : (0));
}

static tcu::IVec4 getNBitSignedIntegerVec4MaxValue (const tcu::IVec4& numBits)
{
	return tcu::IVec4((numBits[0] > 0) ? (deIntMaxValue32(numBits[0])) : (0),
					  (numBits[1] > 0) ? (deIntMaxValue32(numBits[1])) : (0),
					  (numBits[2] > 0) ? (deIntMaxValue32(numBits[2])) : (0),
					  (numBits[3] > 0) ? (deIntMaxValue32(numBits[3])) : (0));
}

static tcu::IVec4 getNBitSignedIntegerVec4MinValue (const tcu::IVec4& numBits)
{
	return tcu::IVec4((numBits[0] > 0) ? (deIntMinValue32(numBits[0])) : (0),
					  (numBits[1] > 0) ? (deIntMinValue32(numBits[1])) : (0),
					  (numBits[2] > 0) ? (deIntMinValue32(numBits[2])) : (0),
					  (numBits[3] > 0) ? (deIntMinValue32(numBits[3])) : (0));
}

static tcu::Vec4 getTextureBorderColorFloat (const TextureFormat& format, const Sampler& sampler)
{
	const tcu::TextureChannelClass	channelClass	= getTextureChannelClass(format.type);
	const TextureSwizzle::Channel*	channelMap		= getBorderColorReadSwizzle(format.order).components;
	const bool						isFloat			= channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT;
	const bool						isSigned		= channelClass != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
	const float						valueMin		= (isSigned) ? (-1.0f) : (0.0f);
	const float						valueMax		= 1.0f;
	Vec4							result;

	DE_ASSERT(channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT ||
			  channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ||
			  channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT);

	for (int c = 0; c < 4; c++)
	{
		const TextureSwizzle::Channel map = channelMap[c];
		if (map == TextureSwizzle::CHANNEL_ZERO)
			result[c] = 0.0f;
		else if (map == TextureSwizzle::CHANNEL_ONE)
			result[c] = 1.0f;
		else if (isFloat)
		{
			// floating point values are not clamped
			result[c] = sampler.borderColor.getAccess<float>()[(int)map];
		}
		else
		{
			// fixed point values are clamped to a representable range
			result[c] = de::clamp(sampler.borderColor.getAccess<float>()[(int)map], valueMin, valueMax);
		}
	}

	return result;
}

static tcu::IVec4 getTextureBorderColorInt (const TextureFormat& format, const Sampler& sampler)
{
	const tcu::TextureChannelClass	channelClass	= getTextureChannelClass(format.type);
	const TextureSwizzle::Channel*	channelMap		= getBorderColorReadSwizzle(format.order).components;
	const IVec4						channelBits		= getChannelBitDepth(format.type);
	const IVec4						valueMin		= getNBitSignedIntegerVec4MinValue(channelBits);
	const IVec4						valueMax		= getNBitSignedIntegerVec4MaxValue(channelBits);
	IVec4							result;

	DE_ASSERT(channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
	DE_UNREF(channelClass);

	for (int c = 0; c < 4; c++)
	{
		const TextureSwizzle::Channel map = channelMap[c];
		if (map == TextureSwizzle::CHANNEL_ZERO)
			result[c] = 0;
		else if (map == TextureSwizzle::CHANNEL_ONE)
			result[c] = 1;
		else
		{
			// integer values are clamped to a representable range
			result[c] = de::clamp(sampler.borderColor.getAccess<deInt32>()[(int)map], valueMin[(int)map], valueMax[(int)map]);
		}
	}

	return result;
}

static tcu::UVec4 getTextureBorderColorUint (const TextureFormat& format, const Sampler& sampler)
{
	const tcu::TextureChannelClass	channelClass	= getTextureChannelClass(format.type);
	const TextureSwizzle::Channel*	channelMap		= getBorderColorReadSwizzle(format.order).components;
	const IVec4						channelBits		= getChannelBitDepth(format.type);
	const UVec4						valueMax		= getNBitUnsignedIntegerVec4MaxValue(channelBits);
	UVec4							result;

	DE_ASSERT(channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
	DE_UNREF(channelClass);

	for (int c = 0; c < 4; c++)
	{
		const TextureSwizzle::Channel map = channelMap[c];
		if (map == TextureSwizzle::CHANNEL_ZERO)
			result[c] = 0;
		else if (map == TextureSwizzle::CHANNEL_ONE)
			result[c] = 1;
		else
		{
			// integer values are clamped to a representable range
			result[c] = de::min(sampler.borderColor.getAccess<deUint32>()[(int)map], valueMax[(int)map]);
		}
	}

	return result;
}

template <typename ScalarType>
tcu::Vector<ScalarType, 4> sampleTextureBorder (const TextureFormat& format, const Sampler& sampler)
{
	const tcu::TextureChannelClass channelClass = getTextureChannelClass(format.type);

	switch (channelClass)
	{
		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
			return getTextureBorderColorFloat(format, sampler).cast<ScalarType>();

		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
			return getTextureBorderColorInt(format, sampler).cast<ScalarType>();

		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
			return getTextureBorderColorUint(format, sampler).cast<ScalarType>();

		default:
			DE_ASSERT(false);
			return tcu::Vector<ScalarType, 4>();
	}
}

// instantiation
template tcu::Vector<float, 4>		sampleTextureBorder (const TextureFormat& format, const Sampler& sampler);
template tcu::Vector<deInt32, 4>	sampleTextureBorder (const TextureFormat& format, const Sampler& sampler);
template tcu::Vector<deUint32, 4>	sampleTextureBorder (const TextureFormat& format, const Sampler& sampler);

} // tcu
