Home | History | Annotate | Download | only in common
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program Tester Core
      3  * ----------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Texture utilities.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "tcuTextureUtil.hpp"
     25 #include "tcuVectorUtil.hpp"
     26 #include "deRandom.hpp"
     27 #include "deMath.h"
     28 #include "deMemory.h"
     29 
     30 #include <limits>
     31 
     32 namespace tcu
     33 {
     34 
     35 static inline float sRGBChannelToLinear (float cs)
     36 {
     37 	if (cs <= 0.04045)
     38 		return cs / 12.92f;
     39 	else
     40 		return deFloatPow((cs + 0.055f) / 1.055f, 2.4f);
     41 }
     42 
     43 static const deUint32 s_srgb8Lut[256] =
     44 {
     45 #include "tcuSRGB8Lut.inl"
     46 };
     47 
     48 static inline float sRGB8ChannelToLinear (deUint32 cs)
     49 {
     50 	DE_ASSERT(cs < 256);
     51 
     52 	// \note This triggers UB, but in practice it doesn't cause any problems
     53 	return ((const float*)s_srgb8Lut)[cs];
     54 }
     55 
     56 static inline float linearChannelToSRGB (float cl)
     57 {
     58 	if (cl <= 0.0f)
     59 		return 0.0f;
     60 	else if (cl < 0.0031308f)
     61 		return 12.92f*cl;
     62 	else if (cl < 1.0f)
     63 		return 1.055f*deFloatPow(cl, 0.41666f) - 0.055f;
     64 	else
     65 		return 1.0f;
     66 }
     67 
     68 //! Convert sRGB to linear colorspace
     69 Vec4 sRGBToLinear (const Vec4& cs)
     70 {
     71 	return Vec4(sRGBChannelToLinear(cs[0]),
     72 				sRGBChannelToLinear(cs[1]),
     73 				sRGBChannelToLinear(cs[2]),
     74 				cs[3]);
     75 }
     76 
     77 Vec4 sRGB8ToLinear (const UVec4& cs)
     78 {
     79 	return Vec4(sRGB8ChannelToLinear(cs[0]),
     80 				sRGB8ChannelToLinear(cs[1]),
     81 				sRGB8ChannelToLinear(cs[2]),
     82 				1.0f);
     83 }
     84 
     85 Vec4 sRGBA8ToLinear (const UVec4& cs)
     86 {
     87 	return Vec4(sRGB8ChannelToLinear(cs[0]),
     88 				sRGB8ChannelToLinear(cs[1]),
     89 				sRGB8ChannelToLinear(cs[2]),
     90 				(float)cs[3] / 255.0f);
     91 }
     92 
     93 //! Convert from linear to sRGB colorspace
     94 Vec4 linearToSRGB (const Vec4& cl)
     95 {
     96 	return Vec4(linearChannelToSRGB(cl[0]),
     97 				linearChannelToSRGB(cl[1]),
     98 				linearChannelToSRGB(cl[2]),
     99 				cl[3]);
    100 }
    101 
    102 bool isSRGB (TextureFormat format)
    103 {
    104 	// make sure to update this if type table is updated
    105 	DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 21);
    106 
    107 	return	format.order == TextureFormat::sR		||
    108 			format.order == TextureFormat::sRG		||
    109 			format.order == TextureFormat::sRGB		||
    110 			format.order == TextureFormat::sRGBA	||
    111 			format.order == TextureFormat::sBGR		||
    112 			format.order == TextureFormat::sBGRA;
    113 }
    114 
    115 tcu::Vec4 linearToSRGBIfNeeded (const TextureFormat& format, const tcu::Vec4& color)
    116 {
    117 	return isSRGB(format) ? linearToSRGB(color) : color;
    118 }
    119 
    120 bool isCombinedDepthStencilType (TextureFormat::ChannelType type)
    121 {
    122 	// make sure to update this if type table is updated
    123 	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40);
    124 
    125 	return	type == TextureFormat::UNSIGNED_INT_16_8_8			||
    126 			type == TextureFormat::UNSIGNED_INT_24_8			||
    127 			type == TextureFormat::UNSIGNED_INT_24_8_REV		||
    128 			type == TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV;
    129 }
    130 
    131 bool hasStencilComponent (TextureFormat::ChannelOrder order)
    132 {
    133 	DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 21);
    134 
    135 	switch (order)
    136 	{
    137 		case TextureFormat::S:
    138 		case TextureFormat::DS:
    139 			return true;
    140 
    141 		default:
    142 			return false;
    143 	}
    144 }
    145 
    146 bool hasDepthComponent (TextureFormat::ChannelOrder order)
    147 {
    148 	DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 21);
    149 
    150 	switch (order)
    151 	{
    152 		case TextureFormat::D:
    153 		case TextureFormat::DS:
    154 			return true;
    155 
    156 		default:
    157 			return false;
    158 	}
    159 }
    160 
    161 //! Get texture channel class for format
    162 TextureChannelClass getTextureChannelClass (TextureFormat::ChannelType channelType)
    163 {
    164 	// make sure this table is updated if format table is updated
    165 	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40);
    166 
    167 	switch (channelType)
    168 	{
    169 		case TextureFormat::SNORM_INT8:						return TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
    170 		case TextureFormat::SNORM_INT16:					return TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
    171 		case TextureFormat::SNORM_INT32:					return TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
    172 		case TextureFormat::UNORM_INT8:						return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
    173 		case TextureFormat::UNORM_INT16:					return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
    174 		case TextureFormat::UNORM_INT24:					return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
    175 		case TextureFormat::UNORM_INT32:					return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
    176 		case TextureFormat::UNORM_BYTE_44:					return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
    177 		case TextureFormat::UNORM_SHORT_565:				return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
    178 		case TextureFormat::UNORM_SHORT_555:				return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
    179 		case TextureFormat::UNORM_SHORT_4444:				return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
    180 		case TextureFormat::UNORM_SHORT_5551:				return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
    181 		case TextureFormat::UNORM_SHORT_1555:				return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
    182 		case TextureFormat::UNSIGNED_BYTE_44:				return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
    183 		case TextureFormat::UNSIGNED_SHORT_565:				return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
    184 		case TextureFormat::UNSIGNED_SHORT_4444:			return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
    185 		case TextureFormat::UNSIGNED_SHORT_5551:			return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
    186 		case TextureFormat::UNORM_INT_101010:				return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
    187 		case TextureFormat::SNORM_INT_1010102_REV:			return TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
    188 		case TextureFormat::UNORM_INT_1010102_REV:			return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
    189 		case TextureFormat::SIGNED_INT_1010102_REV:			return TEXTURECHANNELCLASS_SIGNED_INTEGER;
    190 		case TextureFormat::UNSIGNED_INT_1010102_REV:		return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
    191 		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:	return TEXTURECHANNELCLASS_FLOATING_POINT;
    192 		case TextureFormat::UNSIGNED_INT_999_E5_REV:		return TEXTURECHANNELCLASS_FLOATING_POINT;
    193 		case TextureFormat::UNSIGNED_INT_16_8_8:			return TEXTURECHANNELCLASS_LAST;					//!< packed unorm16-x8-uint8
    194 		case TextureFormat::UNSIGNED_INT_24_8:				return TEXTURECHANNELCLASS_LAST;					//!< packed unorm24-uint8
    195 		case TextureFormat::UNSIGNED_INT_24_8_REV:			return TEXTURECHANNELCLASS_LAST;					//!< packed unorm24-uint8
    196 		case TextureFormat::SIGNED_INT8:					return TEXTURECHANNELCLASS_SIGNED_INTEGER;
    197 		case TextureFormat::SIGNED_INT16:					return TEXTURECHANNELCLASS_SIGNED_INTEGER;
    198 		case TextureFormat::SIGNED_INT32:					return TEXTURECHANNELCLASS_SIGNED_INTEGER;
    199 		case TextureFormat::UNSIGNED_INT8:					return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
    200 		case TextureFormat::UNSIGNED_INT16:					return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
    201 		case TextureFormat::UNSIGNED_INT24:					return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
    202 		case TextureFormat::UNSIGNED_INT32:					return TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
    203 		case TextureFormat::HALF_FLOAT:						return TEXTURECHANNELCLASS_FLOATING_POINT;
    204 		case TextureFormat::FLOAT:							return TEXTURECHANNELCLASS_FLOATING_POINT;
    205 		case TextureFormat::FLOAT64:						return TEXTURECHANNELCLASS_FLOATING_POINT;
    206 		case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:	return TEXTURECHANNELCLASS_LAST;					//!< packed float32-pad24-uint8
    207 		case TextureFormat::UNORM_SHORT_10:					return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
    208 		case TextureFormat::UNORM_SHORT_12:					return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
    209 		default:
    210 			DE_FATAL("Unknown channel type");
    211 			return TEXTURECHANNELCLASS_LAST;
    212 	}
    213 }
    214 
    215 bool isAccessValid (TextureFormat format, TextureAccessType type)
    216 {
    217 	DE_ASSERT(isValid(format));
    218 
    219 	if (format.order == TextureFormat::DS)
    220 	{
    221 		// It is never allowed to access combined depth-stencil format with getPixel().
    222 		// Instead either getPixDepth() or getPixStencil(), or effective depth- or stencil-
    223 		// access must be used.
    224 		return false;
    225 	}
    226 	else if (format.order == TextureFormat::D)
    227 		return type == TEXTUREACCESSTYPE_FLOAT;
    228 	else if (format.order == TextureFormat::S)
    229 		return type == TEXTUREACCESSTYPE_UNSIGNED_INT;
    230 	else
    231 	{
    232 		// A few packed color formats have access type restrictions
    233 		if (format.type == TextureFormat::UNSIGNED_INT_11F_11F_10F_REV ||
    234 			format.type == TextureFormat::UNSIGNED_INT_999_E5_REV)
    235 			return type == TEXTUREACCESSTYPE_FLOAT;
    236 		else
    237 			return true;
    238 	}
    239 }
    240 
    241 /*--------------------------------------------------------------------*//*!
    242  * \brief Get access to subregion of pixel buffer
    243  * \param access	Parent access object
    244  * \param x			X offset
    245  * \param y			Y offset
    246  * \param z			Z offset
    247  * \param width		Width
    248  * \param height	Height
    249  * \param depth		Depth
    250  * \return Access object that targets given subregion of parent access object
    251  *//*--------------------------------------------------------------------*/
    252 ConstPixelBufferAccess getSubregion (const ConstPixelBufferAccess& access, int x, int y, int z, int width, int height, int depth)
    253 {
    254 	DE_ASSERT(de::inBounds(x, 0, access.getWidth()));
    255 	DE_ASSERT(de::inRange(x+width, x+1, access.getWidth()));
    256 
    257 	DE_ASSERT(de::inBounds(y, 0, access.getHeight()));
    258 	DE_ASSERT(de::inRange(y+height, y+1, access.getHeight()));
    259 
    260 	DE_ASSERT(de::inBounds(z, 0, access.getDepth()));
    261 	DE_ASSERT(de::inRange(z+depth, z+1, access.getDepth()));
    262 
    263 	return ConstPixelBufferAccess(access.getFormat(), tcu::IVec3(width, height, depth), access.getPitch(),
    264 								  (const deUint8*)access.getDataPtr() + access.getPixelPitch()*x + access.getRowPitch()*y + access.getSlicePitch()*z);
    265 }
    266 
    267 /*--------------------------------------------------------------------*//*!
    268  * \brief Get access to subregion of pixel buffer
    269  * \param access	Parent access object
    270  * \param x			X offset
    271  * \param y			Y offset
    272  * \param z			Z offset
    273  * \param width		Width
    274  * \param height	Height
    275  * \param depth		Depth
    276  * \return Access object that targets given subregion of parent access object
    277  *//*--------------------------------------------------------------------*/
    278 PixelBufferAccess getSubregion (const PixelBufferAccess& access, int x, int y, int z, int width, int height, int depth)
    279 {
    280 	DE_ASSERT(de::inBounds(x, 0, access.getWidth()));
    281 	DE_ASSERT(de::inRange(x+width, x+1, access.getWidth()));
    282 
    283 	DE_ASSERT(de::inBounds(y, 0, access.getHeight()));
    284 	DE_ASSERT(de::inRange(y+height, y+1, access.getHeight()));
    285 
    286 	DE_ASSERT(de::inBounds(z, 0, access.getDepth()));
    287 	DE_ASSERT(de::inRange(z+depth, z+1, access.getDepth()));
    288 
    289 	return PixelBufferAccess(access.getFormat(), tcu::IVec3(width, height, depth), access.getPitch(),
    290 							 (deUint8*)access.getDataPtr() + access.getPixelPitch()*x + access.getRowPitch()*y + access.getSlicePitch()*z);
    291 }
    292 
    293 /*--------------------------------------------------------------------*//*!
    294  * \brief Get access to subregion of pixel buffer
    295  * \param access	Parent access object
    296  * \param x			X offset
    297  * \param y			Y offset
    298  * \param width		Width
    299  * \param height	Height
    300  * \return Access object that targets given subregion of parent access object
    301  *//*--------------------------------------------------------------------*/
    302 PixelBufferAccess getSubregion (const PixelBufferAccess& access, int x, int y, int width, int height)
    303 {
    304 	return getSubregion(access, x, y, 0, width, height, 1);
    305 }
    306 
    307 /*--------------------------------------------------------------------*//*!
    308  * \brief Get access to subregion of pixel buffer
    309  * \param access	Parent access object
    310  * \param x			X offset
    311  * \param y			Y offset
    312  * \param width		Width
    313  * \param height	Height
    314  * \return Access object that targets given subregion of parent access object
    315  *//*--------------------------------------------------------------------*/
    316 ConstPixelBufferAccess getSubregion (const ConstPixelBufferAccess& access, int x, int y, int width, int height)
    317 {
    318 	return getSubregion(access, x, y, 0, width, height, 1);
    319 }
    320 
    321 /*--------------------------------------------------------------------*//*!
    322  * \brief Flip rows in Y direction
    323  * \param access Access object
    324  * \return Modified access object where Y coordinates are reversed
    325  *//*--------------------------------------------------------------------*/
    326 PixelBufferAccess flipYAccess (const PixelBufferAccess& access)
    327 {
    328 	const int			rowPitch		= access.getRowPitch();
    329 	const int			offsetToLast	= rowPitch*(access.getHeight()-1);
    330 	const tcu::IVec3	pitch			(access.getPixelPitch(), -rowPitch, access.getSlicePitch());
    331 
    332 	return PixelBufferAccess(access.getFormat(), access.getSize(), pitch, (deUint8*)access.getDataPtr() + offsetToLast);
    333 }
    334 
    335 /*--------------------------------------------------------------------*//*!
    336  * \brief Flip rows in Y direction
    337  * \param access Access object
    338  * \return Modified access object where Y coordinates are reversed
    339  *//*--------------------------------------------------------------------*/
    340 ConstPixelBufferAccess flipYAccess (const ConstPixelBufferAccess& access)
    341 {
    342 	const int			rowPitch		= access.getRowPitch();
    343 	const int			offsetToLast	= rowPitch*(access.getHeight()-1);
    344 	const tcu::IVec3	pitch			(access.getPixelPitch(), -rowPitch, access.getSlicePitch());
    345 
    346 	return ConstPixelBufferAccess(access.getFormat(), access.getSize(), pitch, (deUint8*)access.getDataPtr() + offsetToLast);
    347 }
    348 
    349 static Vec2 getFloatChannelValueRange (TextureFormat::ChannelType channelType)
    350 {
    351 	// make sure this table is updated if format table is updated
    352 	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40);
    353 
    354 	float cMin = 0.0f;
    355 	float cMax = 0.0f;
    356 
    357 	switch (channelType)
    358 	{
    359 		// Signed normalized formats.
    360 		case TextureFormat::SNORM_INT8:
    361 		case TextureFormat::SNORM_INT16:
    362 		case TextureFormat::SNORM_INT32:
    363 		case TextureFormat::SNORM_INT_1010102_REV:			cMin = -1.0f;			cMax = 1.0f;			break;
    364 
    365 		// Unsigned normalized formats.
    366 		case TextureFormat::UNORM_INT8:
    367 		case TextureFormat::UNORM_INT16:
    368 		case TextureFormat::UNORM_INT24:
    369 		case TextureFormat::UNORM_INT32:
    370 		case TextureFormat::UNORM_BYTE_44:
    371 		case TextureFormat::UNORM_SHORT_565:
    372 		case TextureFormat::UNORM_SHORT_555:
    373 		case TextureFormat::UNORM_SHORT_4444:
    374 		case TextureFormat::UNORM_SHORT_5551:
    375 		case TextureFormat::UNORM_SHORT_1555:
    376 		case TextureFormat::UNORM_INT_101010:
    377 		case TextureFormat::UNORM_INT_1010102_REV:
    378 		case TextureFormat::UNORM_SHORT_10:
    379 		case TextureFormat::UNORM_SHORT_12:					cMin = 0.0f;			cMax = 1.0f;			break;
    380 
    381 		// Misc formats.
    382 		case TextureFormat::SIGNED_INT8:					cMin = -128.0f;			cMax = 127.0f;			break;
    383 		case TextureFormat::SIGNED_INT16:					cMin = -32768.0f;		cMax = 32767.0f;		break;
    384 		case TextureFormat::SIGNED_INT32:					cMin = -2147483520.0f;	cMax = 2147483520.0f;	break; // Maximum exactly representable 31-bit integer: (2^24 - 1) * 2^7
    385 		case TextureFormat::UNSIGNED_INT8:					cMin = 0.0f;			cMax = 255.0f;			break;
    386 		case TextureFormat::UNSIGNED_INT16:					cMin = 0.0f;			cMax = 65535.0f;		break;
    387 		case TextureFormat::UNSIGNED_INT24:					cMin = 0.0f;			cMax = 16777215.0f;		break;
    388 		case TextureFormat::UNSIGNED_INT32:					cMin = 0.0f;			cMax = 4294967040.f;	break; // Maximum exactly representable 32-bit integer: (2^24 - 1) * 2^8
    389 		case TextureFormat::HALF_FLOAT:						cMin = -1e3f;			cMax = 1e3f;			break;
    390 		case TextureFormat::FLOAT:							cMin = -1e5f;			cMax = 1e5f;			break;
    391 		case TextureFormat::FLOAT64:						cMin = -1e5f;			cMax = 1e5f;			break;
    392 		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:	cMin = 0.0f;			cMax = 1e4f;			break;
    393 		case TextureFormat::UNSIGNED_INT_999_E5_REV:		cMin = 0.0f;			cMax = 1e5f;			break;
    394 		case TextureFormat::UNSIGNED_BYTE_44:				cMin = 0.0f;			cMax = 15.f;			break;
    395 		case TextureFormat::UNSIGNED_SHORT_4444:			cMin = 0.0f;			cMax = 15.f;			break;
    396 
    397 		default:
    398 			DE_ASSERT(false);
    399 	}
    400 
    401 	return Vec2(cMin, cMax);
    402 }
    403 
    404 /*--------------------------------------------------------------------*//*!
    405  * \brief Get standard parameters for testing texture format
    406  *
    407  * Returns TextureFormatInfo that describes good parameters for exercising
    408  * given TextureFormat. Parameters include value ranges per channel and
    409  * suitable lookup scaling and bias in order to reduce result back to
    410  * 0..1 range.
    411  *//*--------------------------------------------------------------------*/
    412 TextureFormatInfo getTextureFormatInfo (const TextureFormat& format)
    413 {
    414 	// Special cases.
    415 	if (format.type == TextureFormat::UNSIGNED_INT_1010102_REV)
    416 		return TextureFormatInfo(Vec4(	     0.0f,		    0.0f,		    0.0f,		 0.0f),
    417 								 Vec4(	  1023.0f,		 1023.0f,		 1023.0f,		 3.0f),
    418 								 Vec4(1.0f/1023.f,	1.0f/1023.0f,	1.0f/1023.0f,	1.0f/3.0f),
    419 								 Vec4(	     0.0f,		    0.0f,		    0.0f,		 0.0f));
    420 	if (format.type == TextureFormat::SIGNED_INT_1010102_REV)
    421 		return TextureFormatInfo(Vec4(	  -512.0f,		 -512.0f,		 -512.0f,		-2.0f),
    422 								 Vec4(	   511.0f,		  511.0f,		  511.0f,		 1.0f),
    423 								 Vec4(1.0f/1023.f,	1.0f/1023.0f,	1.0f/1023.0f,	1.0f/3.0f),
    424 								 Vec4(	     0.5f,		    0.5f,		    0.5f,		 0.5f));
    425 	else if (format.order == TextureFormat::D || format.order == TextureFormat::DS)
    426 		return TextureFormatInfo(Vec4(0.0f,	0.0f,	0.0f,	0.0f),
    427 								 Vec4(1.0f,	1.0f,	1.0f,	0.0f),
    428 								 Vec4(1.0f,	1.0f,	1.0f,	1.0f),
    429 								 Vec4(0.0f,	0.0f,	0.0f,	0.0f)); // Depth / stencil formats.
    430 	else if (format == TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_SHORT_5551))
    431 		return TextureFormatInfo(Vec4(0.0f, 0.0f, 0.0f, 0.5f),
    432 								 Vec4(1.0f, 1.0f, 1.0f, 1.5f),
    433 								 Vec4(1.0f, 1.0f, 1.0f, 1.0f),
    434 								 Vec4(0.0f, 0.0f, 0.0f, 0.0f));
    435 	else if (format.type == TextureFormat::UNSIGNED_SHORT_5551)
    436 		return TextureFormatInfo(Vec4(	   0.0f,		  0.0f,		  0.0f,	0.0f),
    437 								 Vec4(	  31.0f,		 31.0f,		 31.0f,	1.0f),
    438 								 Vec4(1.0f/31.f,	1.0f/31.0f,	1.0f/31.0f,	1.0f),
    439 								 Vec4(	   0.0f,		  0.0f,		  0.0f,	0.0f));
    440 	else if (format.type == TextureFormat::UNSIGNED_SHORT_565)
    441 		return TextureFormatInfo(Vec4(	   0.0f,		  0.0f,		  0.0f,	0.0f),
    442 								 Vec4(	  31.0f,		 63.0f,		 31.0f,	0.0f),
    443 								 Vec4(1.0f/31.f,	1.0f/63.0f,	1.0f/31.0f,	1.0f),
    444 								 Vec4(	   0.0f,		  0.0f,		  0.0f,	0.0f));
    445 
    446 	const Vec2						cRange		= getFloatChannelValueRange(format.type);
    447 	const TextureSwizzle::Channel*	map			= getChannelReadSwizzle(format.order).components;
    448 	const BVec4						chnMask		= BVec4(deInRange32(map[0], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
    449 														deInRange32(map[1], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
    450 														deInRange32(map[2], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
    451 														deInRange32(map[3], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE);
    452 	const float						scale		= 1.0f / (cRange[1] - cRange[0]);
    453 	const float						bias		= -cRange[0] * scale;
    454 
    455 	return TextureFormatInfo(select(cRange[0],	0.0f, chnMask),
    456 							 select(cRange[1],	0.0f, chnMask),
    457 							 select(scale,		1.0f, chnMask),
    458 							 select(bias,		0.0f, chnMask));
    459 }
    460 
    461 IVec4 getFormatMinIntValue (const TextureFormat& format)
    462 {
    463 	DE_ASSERT(getTextureChannelClass(format.type) == TEXTURECHANNELCLASS_SIGNED_INTEGER);
    464 
    465 	switch (format.type)
    466 	{
    467 		case TextureFormat::SIGNED_INT8:	return IVec4(std::numeric_limits<deInt8>::min());
    468 		case TextureFormat::SIGNED_INT16:	return IVec4(std::numeric_limits<deInt16>::min());
    469 		case TextureFormat::SIGNED_INT32:	return IVec4(std::numeric_limits<deInt32>::min());
    470 
    471 		default:
    472 			DE_FATAL("Invalid channel type");
    473 			return IVec4(0);
    474 	}
    475 }
    476 
    477 IVec4 getFormatMaxIntValue (const TextureFormat& format)
    478 {
    479 	DE_ASSERT(getTextureChannelClass(format.type) == TEXTURECHANNELCLASS_SIGNED_INTEGER);
    480 
    481 	if (format == TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT_1010102_REV) ||
    482 		format == TextureFormat(TextureFormat::BGRA, TextureFormat::SIGNED_INT_1010102_REV))
    483 		return IVec4(511, 511, 511, 1);
    484 
    485 	switch (format.type)
    486 	{
    487 		case TextureFormat::SIGNED_INT8:	return IVec4(std::numeric_limits<deInt8>::max());
    488 		case TextureFormat::SIGNED_INT16:	return IVec4(std::numeric_limits<deInt16>::max());
    489 		case TextureFormat::SIGNED_INT32:	return IVec4(std::numeric_limits<deInt32>::max());
    490 
    491 		default:
    492 			DE_FATAL("Invalid channel type");
    493 			return IVec4(0);
    494 	}
    495 }
    496 
    497 UVec4 getFormatMaxUintValue (const TextureFormat& format)
    498 {
    499 	DE_ASSERT(getTextureChannelClass(format.type) == TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
    500 
    501 	if (format == TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT_1010102_REV) ||
    502 		format == TextureFormat(TextureFormat::BGRA, TextureFormat::UNSIGNED_INT_1010102_REV))
    503 		return UVec4(1023u, 1023u, 1023u, 3u);
    504 
    505 	switch (format.type)
    506 	{
    507 		case TextureFormat::UNSIGNED_INT8:	return UVec4(std::numeric_limits<deUint8>::max());
    508 		case TextureFormat::UNSIGNED_INT16:	return UVec4(std::numeric_limits<deUint16>::max());
    509 		case TextureFormat::UNSIGNED_INT24:	return UVec4(0xffffffu);
    510 		case TextureFormat::UNSIGNED_INT32:	return UVec4(std::numeric_limits<deUint32>::max());
    511 
    512 		default:
    513 			DE_FATAL("Invalid channel type");
    514 			return UVec4(0);
    515 	}
    516 }
    517 
    518 static IVec4 getChannelBitDepth (TextureFormat::ChannelType channelType)
    519 {
    520 	// make sure this table is updated if format table is updated
    521 	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40);
    522 
    523 	switch (channelType)
    524 	{
    525 		case TextureFormat::SNORM_INT8:						return IVec4(8);
    526 		case TextureFormat::SNORM_INT16:					return IVec4(16);
    527 		case TextureFormat::SNORM_INT32:					return IVec4(32);
    528 		case TextureFormat::UNORM_INT8:						return IVec4(8);
    529 		case TextureFormat::UNORM_INT16:					return IVec4(16);
    530 		case TextureFormat::UNORM_INT24:					return IVec4(24);
    531 		case TextureFormat::UNORM_INT32:					return IVec4(32);
    532 		case TextureFormat::UNORM_BYTE_44:					return IVec4(4,4,0,0);
    533 		case TextureFormat::UNORM_SHORT_565:				return IVec4(5,6,5,0);
    534 		case TextureFormat::UNORM_SHORT_4444:				return IVec4(4);
    535 		case TextureFormat::UNORM_SHORT_555:				return IVec4(5,5,5,0);
    536 		case TextureFormat::UNORM_SHORT_5551:				return IVec4(5,5,5,1);
    537 		case TextureFormat::UNORM_SHORT_1555:				return IVec4(1,5,5,5);
    538 		case TextureFormat::UNSIGNED_BYTE_44:				return IVec4(4,4,0,0);
    539 		case TextureFormat::UNSIGNED_SHORT_565:				return IVec4(5,6,5,0);
    540 		case TextureFormat::UNSIGNED_SHORT_4444:			return IVec4(4);
    541 		case TextureFormat::UNSIGNED_SHORT_5551:			return IVec4(5,5,5,1);
    542 		case TextureFormat::UNORM_INT_101010:				return IVec4(10,10,10,0);
    543 		case TextureFormat::SNORM_INT_1010102_REV:			return IVec4(10,10,10,2);
    544 		case TextureFormat::UNORM_INT_1010102_REV:			return IVec4(10,10,10,2);
    545 		case TextureFormat::SIGNED_INT8:					return IVec4(8);
    546 		case TextureFormat::SIGNED_INT16:					return IVec4(16);
    547 		case TextureFormat::SIGNED_INT32:					return IVec4(32);
    548 		case TextureFormat::UNSIGNED_INT8:					return IVec4(8);
    549 		case TextureFormat::UNSIGNED_INT16:					return IVec4(16);
    550 		case TextureFormat::UNSIGNED_INT24:					return IVec4(24);
    551 		case TextureFormat::UNSIGNED_INT32:					return IVec4(32);
    552 		case TextureFormat::SIGNED_INT_1010102_REV:			return IVec4(10,10,10,2);
    553 		case TextureFormat::UNSIGNED_INT_1010102_REV:		return IVec4(10,10,10,2);
    554 		case TextureFormat::UNSIGNED_INT_16_8_8:			return IVec4(16,8,0,0);
    555 		case TextureFormat::UNSIGNED_INT_24_8:				return IVec4(24,8,0,0);
    556 		case TextureFormat::UNSIGNED_INT_24_8_REV:			return IVec4(24,8,0,0);
    557 		case TextureFormat::HALF_FLOAT:						return IVec4(16);
    558 		case TextureFormat::FLOAT:							return IVec4(32);
    559 		case TextureFormat::FLOAT64:						return IVec4(64);
    560 		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:	return IVec4(11,11,10,0);
    561 		case TextureFormat::UNSIGNED_INT_999_E5_REV:		return IVec4(9,9,9,0);
    562 		case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:	return IVec4(32,8,0,0);
    563 		case TextureFormat::UNORM_SHORT_10:					return IVec4(10);
    564 		case TextureFormat::UNORM_SHORT_12:					return IVec4(12);
    565 		default:
    566 			DE_ASSERT(false);
    567 			return IVec4(0);
    568 	}
    569 }
    570 
    571 IVec4 getTextureFormatBitDepth (const TextureFormat& format)
    572 {
    573 	const IVec4						chnBits		= getChannelBitDepth(format.type);
    574 	const TextureSwizzle::Channel*	map			= getChannelReadSwizzle(format.order).components;
    575 	const BVec4						chnMask		= BVec4(deInRange32(map[0], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
    576 														deInRange32(map[1], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
    577 														deInRange32(map[2], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
    578 														deInRange32(map[3], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE);
    579 	const IVec4						chnSwz		= IVec4((chnMask[0]) ? ((int)map[0]) : (0),
    580 														(chnMask[1]) ? ((int)map[1]) : (0),
    581 														(chnMask[2]) ? ((int)map[2]) : (0),
    582 														(chnMask[3]) ? ((int)map[3]) : (0));
    583 
    584 	return select(chnBits.swizzle(chnSwz.x(), chnSwz.y(), chnSwz.z(), chnSwz.w()), IVec4(0), chnMask);
    585 }
    586 
    587 static IVec4 getChannelMantissaBitDepth (TextureFormat::ChannelType channelType)
    588 {
    589 	// make sure this table is updated if format table is updated
    590 	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40);
    591 
    592 	switch (channelType)
    593 	{
    594 		case TextureFormat::SNORM_INT8:
    595 		case TextureFormat::SNORM_INT16:
    596 		case TextureFormat::SNORM_INT32:
    597 		case TextureFormat::UNORM_INT8:
    598 		case TextureFormat::UNORM_INT16:
    599 		case TextureFormat::UNORM_INT24:
    600 		case TextureFormat::UNORM_INT32:
    601 		case TextureFormat::UNORM_BYTE_44:
    602 		case TextureFormat::UNORM_SHORT_565:
    603 		case TextureFormat::UNORM_SHORT_4444:
    604 		case TextureFormat::UNORM_SHORT_555:
    605 		case TextureFormat::UNORM_SHORT_5551:
    606 		case TextureFormat::UNORM_SHORT_1555:
    607 		case TextureFormat::UNSIGNED_BYTE_44:
    608 		case TextureFormat::UNSIGNED_SHORT_565:
    609 		case TextureFormat::UNSIGNED_SHORT_4444:
    610 		case TextureFormat::UNSIGNED_SHORT_5551:
    611 		case TextureFormat::UNORM_INT_101010:
    612 		case TextureFormat::SNORM_INT_1010102_REV:
    613 		case TextureFormat::UNORM_INT_1010102_REV:
    614 		case TextureFormat::SIGNED_INT8:
    615 		case TextureFormat::SIGNED_INT16:
    616 		case TextureFormat::SIGNED_INT32:
    617 		case TextureFormat::UNSIGNED_INT8:
    618 		case TextureFormat::UNSIGNED_INT16:
    619 		case TextureFormat::UNSIGNED_INT24:
    620 		case TextureFormat::UNSIGNED_INT32:
    621 		case TextureFormat::SIGNED_INT_1010102_REV:
    622 		case TextureFormat::UNSIGNED_INT_1010102_REV:
    623 		case TextureFormat::UNSIGNED_INT_16_8_8:
    624 		case TextureFormat::UNSIGNED_INT_24_8:
    625 		case TextureFormat::UNSIGNED_INT_24_8_REV:
    626 		case TextureFormat::UNSIGNED_INT_999_E5_REV:
    627 		case TextureFormat::UNORM_SHORT_10:
    628 		case TextureFormat::UNORM_SHORT_12:
    629 			return getChannelBitDepth(channelType);
    630 
    631 		case TextureFormat::HALF_FLOAT:						return IVec4(10);
    632 		case TextureFormat::FLOAT:							return IVec4(23);
    633 		case TextureFormat::FLOAT64:						return IVec4(52);
    634 		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:	return IVec4(6,6,5,0);
    635 		case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:	return IVec4(23,8,0,0);
    636 		default:
    637 			DE_ASSERT(false);
    638 			return IVec4(0);
    639 	}
    640 }
    641 
    642 IVec4 getTextureFormatMantissaBitDepth (const TextureFormat& format)
    643 {
    644 	const IVec4						chnBits		= getChannelMantissaBitDepth(format.type);
    645 	const TextureSwizzle::Channel*	map			= getChannelReadSwizzle(format.order).components;
    646 	const BVec4						chnMask		= BVec4(deInRange32(map[0], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
    647 														deInRange32(map[1], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
    648 														deInRange32(map[2], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
    649 														deInRange32(map[3], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE);
    650 	const IVec4						chnSwz		= IVec4((chnMask[0]) ? ((int)map[0]) : (0),
    651 														(chnMask[1]) ? ((int)map[1]) : (0),
    652 														(chnMask[2]) ? ((int)map[2]) : (0),
    653 														(chnMask[3]) ? ((int)map[3]) : (0));
    654 
    655 	return select(chnBits.swizzle(chnSwz.x(), chnSwz.y(), chnSwz.z(), chnSwz.w()), IVec4(0), chnMask);
    656 }
    657 
    658 BVec4 getTextureFormatChannelMask (const TextureFormat& format)
    659 {
    660 	const TextureSwizzle::Channel* const map = getChannelReadSwizzle(format.order).components;
    661 	return BVec4(deInRange32(map[0], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
    662 				 deInRange32(map[1], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
    663 				 deInRange32(map[2], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
    664 				 deInRange32(map[3], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE);
    665 }
    666 
    667 static inline float linearInterpolate (float t, float minVal, float maxVal)
    668 {
    669 	return minVal + (maxVal - minVal) * t;
    670 }
    671 
    672 static inline Vec4 linearInterpolate (float t, const Vec4& a, const Vec4& b)
    673 {
    674 	return a + (b - a) * t;
    675 }
    676 
    677 enum
    678 {
    679 	CLEAR_OPTIMIZE_THRESHOLD		= 128,
    680 	CLEAR_OPTIMIZE_MAX_PIXEL_SIZE	= 8
    681 };
    682 
    683 inline void fillRow (const PixelBufferAccess& dst, int y, int z, int pixelSize, const deUint8* pixel)
    684 {
    685 	DE_ASSERT(dst.getPixelPitch() == pixelSize); // only tightly packed
    686 
    687 	deUint8*	dstPtr	= (deUint8*)dst.getPixelPtr(0, y, z);
    688 	int			width	= dst.getWidth();
    689 
    690 	if (pixelSize == 8 && deIsAlignedPtr(dstPtr, pixelSize))
    691 	{
    692 		deUint64 val;
    693 		memcpy(&val, pixel, sizeof(val));
    694 
    695 		for (int i = 0; i < width; i++)
    696 			((deUint64*)dstPtr)[i] = val;
    697 	}
    698 	else if (pixelSize == 4 && deIsAlignedPtr(dstPtr, pixelSize))
    699 	{
    700 		deUint32 val;
    701 		memcpy(&val, pixel, sizeof(val));
    702 
    703 		for (int i = 0; i < width; i++)
    704 			((deUint32*)dstPtr)[i] = val;
    705 	}
    706 	else
    707 	{
    708 		for (int i = 0; i < width; i++)
    709 			for (int j = 0; j < pixelSize; j++)
    710 				dstPtr[i*pixelSize+j] = pixel[j];
    711 	}
    712 }
    713 
    714 void clear (const PixelBufferAccess& access, const Vec4& color)
    715 {
    716 	const int	pixelSize				= access.getFormat().getPixelSize();
    717 	const int	pixelPitch				= access.getPixelPitch();
    718 	const bool	rowPixelsTightlyPacked	= (pixelSize == pixelPitch);
    719 
    720 	if (access.getWidth()*access.getHeight()*access.getDepth() >= CLEAR_OPTIMIZE_THRESHOLD &&
    721 		pixelSize < CLEAR_OPTIMIZE_MAX_PIXEL_SIZE && rowPixelsTightlyPacked)
    722 	{
    723 		// Convert to destination format.
    724 		union
    725 		{
    726 			deUint8		u8[CLEAR_OPTIMIZE_MAX_PIXEL_SIZE];
    727 			deUint64	u64; // Forces 64-bit alignment.
    728 		} pixel;
    729 		DE_STATIC_ASSERT(sizeof(pixel) == CLEAR_OPTIMIZE_MAX_PIXEL_SIZE);
    730 		PixelBufferAccess(access.getFormat(), 1, 1, 1, 0, 0, &pixel.u8[0]).setPixel(color, 0, 0);
    731 
    732 		for (int z = 0; z < access.getDepth(); z++)
    733 			for (int y = 0; y < access.getHeight(); y++)
    734 				fillRow(access, y, z, pixelSize, &pixel.u8[0]);
    735 	}
    736 	else
    737 	{
    738 		for (int z = 0; z < access.getDepth(); z++)
    739 			for (int y = 0; y < access.getHeight(); y++)
    740 				for (int x = 0; x < access.getWidth(); x++)
    741 					access.setPixel(color, x, y, z);
    742 	}
    743 }
    744 
    745 void clear (const PixelBufferAccess& access, const IVec4& color)
    746 {
    747 	const int	pixelSize				= access.getFormat().getPixelSize();
    748 	const int	pixelPitch				= access.getPixelPitch();
    749 	const bool	rowPixelsTightlyPacked	= (pixelSize == pixelPitch);
    750 
    751 	if (access.getWidth()*access.getHeight()*access.getDepth() >= CLEAR_OPTIMIZE_THRESHOLD &&
    752 		pixelSize < CLEAR_OPTIMIZE_MAX_PIXEL_SIZE && rowPixelsTightlyPacked)
    753 	{
    754 		// Convert to destination format.
    755 		union
    756 		{
    757 			deUint8		u8[CLEAR_OPTIMIZE_MAX_PIXEL_SIZE];
    758 			deUint64	u64; // Forces 64-bit alignment.
    759 		} pixel;
    760 		DE_STATIC_ASSERT(sizeof(pixel) == CLEAR_OPTIMIZE_MAX_PIXEL_SIZE);
    761 		PixelBufferAccess(access.getFormat(), 1, 1, 1, 0, 0, &pixel.u8[0]).setPixel(color, 0, 0);
    762 
    763 		for (int z = 0; z < access.getDepth(); z++)
    764 			for (int y = 0; y < access.getHeight(); y++)
    765 				fillRow(access, y, z, pixelSize, &pixel.u8[0]);
    766 	}
    767 	else
    768 	{
    769 		for (int z = 0; z < access.getDepth(); z++)
    770 			for (int y = 0; y < access.getHeight(); y++)
    771 				for (int x = 0; x < access.getWidth(); x++)
    772 					access.setPixel(color, x, y, z);
    773 	}
    774 }
    775 
    776 void clear (const PixelBufferAccess& access, const UVec4& color)
    777 {
    778 	clear(access, color.cast<deInt32>());
    779 }
    780 
    781 void clearDepth (const PixelBufferAccess& access, float depth)
    782 {
    783 	DE_ASSERT(access.getFormat().order == TextureFormat::DS || access.getFormat().order == TextureFormat::D);
    784 
    785 	clear(getEffectiveDepthStencilAccess(access, Sampler::MODE_DEPTH), tcu::Vec4(depth, 0.0f, 0.0f, 0.0f));
    786 }
    787 
    788 void clearStencil (const PixelBufferAccess& access, int stencil)
    789 {
    790 	DE_ASSERT(access.getFormat().order == TextureFormat::DS || access.getFormat().order == TextureFormat::S);
    791 
    792 	clear(getEffectiveDepthStencilAccess(access, Sampler::MODE_STENCIL), tcu::UVec4(stencil, 0u, 0u, 0u));
    793 }
    794 
    795 static void fillWithComponentGradients1D (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal)
    796 {
    797 	DE_ASSERT(access.getHeight() == 1);
    798 	for (int x = 0; x < access.getWidth(); x++)
    799 	{
    800 		float s = ((float)x + 0.5f) / (float)access.getWidth();
    801 
    802 		float r = linearInterpolate(s, minVal.x(), maxVal.x());
    803 		float g = linearInterpolate(s, minVal.y(), maxVal.y());
    804 		float b = linearInterpolate(s, minVal.z(), maxVal.z());
    805 		float a = linearInterpolate(s, minVal.w(), maxVal.w());
    806 
    807 		access.setPixel(tcu::Vec4(r, g, b, a), x, 0);
    808 	}
    809 }
    810 
    811 static void fillWithComponentGradients2D (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal)
    812 {
    813 	for (int y = 0; y < access.getHeight(); y++)
    814 	{
    815 		for (int x = 0; x < access.getWidth(); x++)
    816 		{
    817 			float s = ((float)x + 0.5f) / (float)access.getWidth();
    818 			float t = ((float)y + 0.5f) / (float)access.getHeight();
    819 
    820 			float r = linearInterpolate((      s  +       t) *0.5f, minVal.x(), maxVal.x());
    821 			float g = linearInterpolate((      s  + (1.0f-t))*0.5f, minVal.y(), maxVal.y());
    822 			float b = linearInterpolate(((1.0f-s) +       t) *0.5f, minVal.z(), maxVal.z());
    823 			float a = linearInterpolate(((1.0f-s) + (1.0f-t))*0.5f, minVal.w(), maxVal.w());
    824 
    825 			access.setPixel(tcu::Vec4(r, g, b, a), x, y);
    826 		}
    827 	}
    828 }
    829 
    830 static void fillWithComponentGradients3D (const PixelBufferAccess& dst, const Vec4& minVal, const Vec4& maxVal)
    831 {
    832 	for (int z = 0; z < dst.getDepth(); z++)
    833 	{
    834 		for (int y = 0; y < dst.getHeight(); y++)
    835 		{
    836 			for (int x = 0; x < dst.getWidth(); x++)
    837 			{
    838 				float s = ((float)x + 0.5f) / (float)dst.getWidth();
    839 				float t = ((float)y + 0.5f) / (float)dst.getHeight();
    840 				float p = ((float)z + 0.5f) / (float)dst.getDepth();
    841 
    842 				float r = linearInterpolate(s,						minVal.x(), maxVal.x());
    843 				float g = linearInterpolate(t,						minVal.y(), maxVal.y());
    844 				float b = linearInterpolate(p,						minVal.z(), maxVal.z());
    845 				float a = linearInterpolate(1.0f - (s+t+p)/3.0f,	minVal.w(), maxVal.w());
    846 
    847 				dst.setPixel(tcu::Vec4(r, g, b, a), x, y, z);
    848 			}
    849 		}
    850 	}
    851 }
    852 
    853 void fillWithComponentGradients (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal)
    854 {
    855 	if (isCombinedDepthStencilType(access.getFormat().type))
    856 	{
    857 		const bool hasDepth		= access.getFormat().order == tcu::TextureFormat::DS || access.getFormat().order == tcu::TextureFormat::D;
    858 		const bool hasStencil	= access.getFormat().order == tcu::TextureFormat::DS || access.getFormat().order == tcu::TextureFormat::S;
    859 
    860 		DE_ASSERT(hasDepth || hasStencil);
    861 
    862 		// For combined formats, treat D and S as separate channels
    863 		if (hasDepth)
    864 			fillWithComponentGradients(getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_DEPTH), minVal, maxVal);
    865 		if (hasStencil)
    866 			fillWithComponentGradients(getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_STENCIL), minVal.swizzle(3,2,1,0), maxVal.swizzle(3,2,1,0));
    867 	}
    868 	else
    869 	{
    870 		if (access.getHeight() == 1 && access.getDepth() == 1)
    871 			fillWithComponentGradients1D(access, minVal, maxVal);
    872 		else if (access.getDepth() == 1)
    873 			fillWithComponentGradients2D(access, minVal, maxVal);
    874 		else
    875 			fillWithComponentGradients3D(access, minVal, maxVal);
    876 	}
    877 }
    878 
    879 static void fillWithGrid1D (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB)
    880 {
    881 	for (int x = 0; x < access.getWidth(); x++)
    882 	{
    883 		int mx = (x / cellSize) % 2;
    884 
    885 		if (mx)
    886 			access.setPixel(colorB, x, 0);
    887 		else
    888 			access.setPixel(colorA, x, 0);
    889 	}
    890 }
    891 
    892 static void fillWithGrid2D (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB)
    893 {
    894 	for (int y = 0; y < access.getHeight(); y++)
    895 	{
    896 		for (int x = 0; x < access.getWidth(); x++)
    897 		{
    898 			int mx = (x / cellSize) % 2;
    899 			int my = (y / cellSize) % 2;
    900 
    901 			if (mx ^ my)
    902 				access.setPixel(colorB, x, y);
    903 			else
    904 				access.setPixel(colorA, x, y);
    905 		}
    906 	}
    907 }
    908 
    909 static void fillWithGrid3D (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB)
    910 {
    911 	for (int z = 0; z < access.getDepth(); z++)
    912 	{
    913 		for (int y = 0; y < access.getHeight(); y++)
    914 		{
    915 			for (int x = 0; x < access.getWidth(); x++)
    916 			{
    917 				int mx = (x / cellSize) % 2;
    918 				int my = (y / cellSize) % 2;
    919 				int mz = (z / cellSize) % 2;
    920 
    921 				if (mx ^ my ^ mz)
    922 					access.setPixel(colorB, x, y, z);
    923 				else
    924 					access.setPixel(colorA, x, y, z);
    925 			}
    926 		}
    927 	}
    928 }
    929 
    930 void fillWithGrid (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB)
    931 {
    932 	if (isCombinedDepthStencilType(access.getFormat().type))
    933 	{
    934 		const bool hasDepth		= access.getFormat().order == tcu::TextureFormat::DS || access.getFormat().order == tcu::TextureFormat::D;
    935 		const bool hasStencil	= access.getFormat().order == tcu::TextureFormat::DS || access.getFormat().order == tcu::TextureFormat::S;
    936 
    937 		DE_ASSERT(hasDepth || hasStencil);
    938 
    939 		// For combined formats, treat D and S as separate channels
    940 		if (hasDepth)
    941 			fillWithGrid(getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_DEPTH), cellSize, colorA, colorB);
    942 		if (hasStencil)
    943 			fillWithGrid(getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_STENCIL), cellSize, colorA.swizzle(3,2,1,0), colorB.swizzle(3,2,1,0));
    944 	}
    945 	else
    946 	{
    947 		if (access.getHeight() == 1 && access.getDepth() == 1)
    948 			fillWithGrid1D(access, cellSize, colorA, colorB);
    949 		else if (access.getDepth() == 1)
    950 			fillWithGrid2D(access, cellSize, colorA, colorB);
    951 		else
    952 			fillWithGrid3D(access, cellSize, colorA, colorB);
    953 	}
    954 }
    955 
    956 void fillWithRepeatableGradient (const PixelBufferAccess& access, const Vec4& colorA, const Vec4& colorB)
    957 {
    958 	for (int y = 0; y < access.getHeight(); y++)
    959 	{
    960 		for (int x = 0; x < access.getWidth(); x++)
    961 		{
    962 			float s = ((float)x + 0.5f) / (float)access.getWidth();
    963 			float t = ((float)y + 0.5f) / (float)access.getHeight();
    964 
    965 			float a = s > 0.5f ? (2.0f - 2.0f*s) : 2.0f*s;
    966 			float b = t > 0.5f ? (2.0f - 2.0f*t) : 2.0f*t;
    967 
    968 			float p = deFloatClamp(deFloatSqrt(a*a + b*b), 0.0f, 1.0f);
    969 			access.setPixel(linearInterpolate(p, colorA, colorB), x, y);
    970 		}
    971 	}
    972 }
    973 
    974 void fillWithRGBAQuads (const PixelBufferAccess& dst)
    975 {
    976 	TCU_CHECK_INTERNAL(dst.getDepth() == 1);
    977 	int width	= dst.getWidth();
    978 	int height	= dst.getHeight();
    979 	int	left	= width/2;
    980 	int top		= height/2;
    981 
    982 	clear(getSubregion(dst, 0,		0,		0, left,		top,		1),	Vec4(1.0f, 0.0f, 0.0f, 1.0f));
    983 	clear(getSubregion(dst, left,	0,		0, width-left,	top,		1),	Vec4(0.0f, 1.0f, 0.0f, 1.0f));
    984 	clear(getSubregion(dst, 0,		top,	0, left,		height-top,	1), Vec4(0.0f, 0.0f, 1.0f, 0.0f));
    985 	clear(getSubregion(dst, left,	top,	0, width-left,	height-top, 1), Vec4(0.5f, 0.5f, 0.5f, 1.0f));
    986 }
    987 
    988 // \todo [2012-11-13 pyry] There is much better metaballs code in CL SIR value generators.
    989 void fillWithMetaballs (const PixelBufferAccess& dst, int numBalls, deUint32 seed)
    990 {
    991 	TCU_CHECK_INTERNAL(dst.getDepth() == 1);
    992 	std::vector<Vec2>	points(numBalls);
    993 	de::Random			rnd(seed);
    994 
    995 	for (int i = 0; i < numBalls; i++)
    996 	{
    997 		float x = rnd.getFloat();
    998 		float y = rnd.getFloat();
    999 		points[i] = (Vec2(x, y));
   1000 	}
   1001 
   1002 	for (int y = 0; y < dst.getHeight(); y++)
   1003 	for (int x = 0; x < dst.getWidth(); x++)
   1004 	{
   1005 		Vec2 p((float)x/(float)dst.getWidth(), (float)y/(float)dst.getHeight());
   1006 
   1007 		float sum = 0.0f;
   1008 		for (std::vector<Vec2>::const_iterator i = points.begin(); i != points.end(); i++)
   1009 		{
   1010 			Vec2	d = p - *i;
   1011 			float	f = 0.01f / (d.x()*d.x() + d.y()*d.y());
   1012 
   1013 			sum += f;
   1014 		}
   1015 
   1016 		dst.setPixel(Vec4(sum), x, y);
   1017 	}
   1018 }
   1019 
   1020 void copy (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src)
   1021 {
   1022 	DE_ASSERT(src.getSize() == dst.getSize());
   1023 
   1024 	const int	width				= dst.getWidth();
   1025 	const int	height				= dst.getHeight();
   1026 	const int	depth				= dst.getDepth();
   1027 
   1028 	const int	srcPixelSize		= src.getFormat().getPixelSize();
   1029 	const int	dstPixelSize		= dst.getFormat().getPixelSize();
   1030 	const int	srcPixelPitch		= src.getPixelPitch();
   1031 	const int	dstPixelPitch		= dst.getPixelPitch();
   1032 	const bool	srcTightlyPacked	= (srcPixelSize == srcPixelPitch);
   1033 	const bool	dstTightlyPacked	= (dstPixelSize == dstPixelPitch);
   1034 
   1035 	const bool	srcHasDepth			= (src.getFormat().order == tcu::TextureFormat::DS || src.getFormat().order == tcu::TextureFormat::D);
   1036 	const bool	srcHasStencil		= (src.getFormat().order == tcu::TextureFormat::DS || src.getFormat().order == tcu::TextureFormat::S);
   1037 	const bool	dstHasDepth			= (dst.getFormat().order == tcu::TextureFormat::DS || dst.getFormat().order == tcu::TextureFormat::D);
   1038 	const bool	dstHasStencil		= (dst.getFormat().order == tcu::TextureFormat::DS || dst.getFormat().order == tcu::TextureFormat::S);
   1039 
   1040 	if (src.getFormat() == dst.getFormat() && srcTightlyPacked && dstTightlyPacked)
   1041 	{
   1042 		// Fast-path for matching formats.
   1043 		for (int z = 0; z < depth; z++)
   1044 		for (int y = 0; y < height; y++)
   1045 			deMemcpy(dst.getPixelPtr(0, y, z), src.getPixelPtr(0, y, z), srcPixelSize*width);
   1046 	}
   1047 	else if (src.getFormat() == dst.getFormat())
   1048 	{
   1049 		// Bit-exact copy for matching formats.
   1050 		for (int z = 0; z < depth; z++)
   1051 		for (int y = 0; y < height; y++)
   1052 		for (int x = 0; x < width; x++)
   1053 			deMemcpy(dst.getPixelPtr(x, y, z), src.getPixelPtr(x, y, z), srcPixelSize);
   1054 	}
   1055 	else if (srcHasDepth || srcHasStencil || dstHasDepth || dstHasStencil)
   1056 	{
   1057 		DE_ASSERT((srcHasDepth && dstHasDepth) || (srcHasStencil && dstHasStencil)); // must have at least one common channel
   1058 
   1059 		if (dstHasDepth && srcHasDepth)
   1060 		{
   1061 			for (int z = 0; z < depth; z++)
   1062 			for (int y = 0; y < height; y++)
   1063 			for (int x = 0; x < width; x++)
   1064 				dst.setPixDepth(src.getPixDepth(x, y, z), x, y, z);
   1065 		}
   1066 		else if (dstHasDepth && !srcHasDepth)
   1067 		{
   1068 			// consistency with color copies
   1069 			tcu::clearDepth(dst, 0.0f);
   1070 		}
   1071 
   1072 		if (dstHasStencil && srcHasStencil)
   1073 		{
   1074 			for (int z = 0; z < depth; z++)
   1075 			for (int y = 0; y < height; y++)
   1076 			for (int x = 0; x < width; x++)
   1077 				dst.setPixStencil(src.getPixStencil(x, y, z), x, y, z);
   1078 		}
   1079 		else if (dstHasStencil && !srcHasStencil)
   1080 		{
   1081 			// consistency with color copies
   1082 			tcu::clearStencil(dst, 0u);
   1083 		}
   1084 	}
   1085 	else
   1086 	{
   1087 		TextureChannelClass		srcClass	= getTextureChannelClass(src.getFormat().type);
   1088 		TextureChannelClass		dstClass	= getTextureChannelClass(dst.getFormat().type);
   1089 		bool					srcIsInt	= srcClass == TEXTURECHANNELCLASS_SIGNED_INTEGER || srcClass == TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
   1090 		bool					dstIsInt	= dstClass == TEXTURECHANNELCLASS_SIGNED_INTEGER || dstClass == TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
   1091 
   1092 		if (srcIsInt && dstIsInt)
   1093 		{
   1094 			for (int z = 0; z < depth; z++)
   1095 			for (int y = 0; y < height; y++)
   1096 			for (int x = 0; x < width; x++)
   1097 				dst.setPixel(src.getPixelInt(x, y, z), x, y, z);
   1098 		}
   1099 		else
   1100 		{
   1101 			for (int z = 0; z < depth; z++)
   1102 			for (int y = 0; y < height; y++)
   1103 			for (int x = 0; x < width; x++)
   1104 				dst.setPixel(src.getPixel(x, y, z), x, y, z);
   1105 		}
   1106 	}
   1107 }
   1108 
   1109 void scale (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src, Sampler::FilterMode filter)
   1110 {
   1111 	DE_ASSERT(filter == Sampler::NEAREST || filter == Sampler::LINEAR);
   1112 
   1113 	Sampler sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE,
   1114 					filter, filter, 0.0f, false);
   1115 
   1116 	float sX = (float)src.getWidth() / (float)dst.getWidth();
   1117 	float sY = (float)src.getHeight() / (float)dst.getHeight();
   1118 	float sZ = (float)src.getDepth() / (float)dst.getDepth();
   1119 
   1120 	if (dst.getDepth() == 1 && src.getDepth() == 1)
   1121 	{
   1122 		for (int y = 0; y < dst.getHeight(); y++)
   1123 		for (int x = 0; x < dst.getWidth(); x++)
   1124 			dst.setPixel(linearToSRGBIfNeeded(dst.getFormat(), src.sample2D(sampler, filter, ((float)x+0.5f)*sX, ((float)y+0.5f)*sY, 0)), x, y);
   1125 	}
   1126 	else
   1127 	{
   1128 		for (int z = 0; z < dst.getDepth(); z++)
   1129 		for (int y = 0; y < dst.getHeight(); y++)
   1130 		for (int x = 0; x < dst.getWidth(); x++)
   1131 			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);
   1132 	}
   1133 }
   1134 
   1135 void estimatePixelValueRange (const ConstPixelBufferAccess& access, Vec4& minVal, Vec4& maxVal)
   1136 {
   1137 	const TextureFormat& format = access.getFormat();
   1138 
   1139 	switch (getTextureChannelClass(format.type))
   1140 	{
   1141 		case TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
   1142 			// Normalized unsigned formats.
   1143 			minVal = Vec4(0.0f);
   1144 			maxVal = Vec4(1.0f);
   1145 			break;
   1146 
   1147 		case TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
   1148 			// Normalized signed formats.
   1149 			minVal = Vec4(-1.0f);
   1150 			maxVal = Vec4(+1.0f);
   1151 			break;
   1152 
   1153 		default:
   1154 			// \note Samples every 4/8th pixel.
   1155 			minVal = Vec4(std::numeric_limits<float>::max());
   1156 			maxVal = Vec4(std::numeric_limits<float>::min());
   1157 
   1158 			for (int z = 0; z < access.getDepth(); z += 2)
   1159 			{
   1160 				for (int y = 0; y < access.getHeight(); y += 2)
   1161 				{
   1162 					for (int x = 0; x < access.getWidth(); x += 2)
   1163 					{
   1164 						Vec4 p = access.getPixel(x, y, z);
   1165 
   1166 						minVal[0] = (deFloatIsNaN(p[0]) ? minVal[0] : de::min(minVal[0], p[0]));
   1167 						minVal[1] = (deFloatIsNaN(p[1]) ? minVal[1] : de::min(minVal[1], p[1]));
   1168 						minVal[2] = (deFloatIsNaN(p[2]) ? minVal[2] : de::min(minVal[2], p[2]));
   1169 						minVal[3] = (deFloatIsNaN(p[3]) ? minVal[3] : de::min(minVal[3], p[3]));
   1170 
   1171 						maxVal[0] = (deFloatIsNaN(p[0]) ? maxVal[0] : de::max(maxVal[0], p[0]));
   1172 						maxVal[1] = (deFloatIsNaN(p[1]) ? maxVal[1] : de::max(maxVal[1], p[1]));
   1173 						maxVal[2] = (deFloatIsNaN(p[2]) ? maxVal[2] : de::max(maxVal[2], p[2]));
   1174 						maxVal[3] = (deFloatIsNaN(p[3]) ? maxVal[3] : de::max(maxVal[3], p[3]));
   1175 					}
   1176 				}
   1177 			}
   1178 			break;
   1179 	}
   1180 }
   1181 
   1182 void computePixelScaleBias (const ConstPixelBufferAccess& access, Vec4& scale, Vec4& bias)
   1183 {
   1184 	Vec4 minVal, maxVal;
   1185 	estimatePixelValueRange(access, minVal, maxVal);
   1186 
   1187 	const float eps = 0.0001f;
   1188 
   1189 	for (int c = 0; c < 4; c++)
   1190 	{
   1191 		if (maxVal[c] - minVal[c] < eps)
   1192 		{
   1193 			scale[c]	= (maxVal[c] < eps) ? 1.0f : (1.0f / maxVal[c]);
   1194 			bias[c]		= (c == 3) ? (1.0f - maxVal[c]*scale[c]) : (0.0f - minVal[c]*scale[c]);
   1195 		}
   1196 		else
   1197 		{
   1198 			scale[c]	= 1.0f / (maxVal[c] - minVal[c]);
   1199 			bias[c]		= 0.0f - minVal[c]*scale[c];
   1200 		}
   1201 	}
   1202 }
   1203 
   1204 int getCubeArrayFaceIndex (CubeFace face)
   1205 {
   1206 	DE_ASSERT((int)face >= 0 && face < CUBEFACE_LAST);
   1207 
   1208 	switch (face)
   1209 	{
   1210 		case CUBEFACE_POSITIVE_X:	return 0;
   1211 		case CUBEFACE_NEGATIVE_X:	return 1;
   1212 		case CUBEFACE_POSITIVE_Y:	return 2;
   1213 		case CUBEFACE_NEGATIVE_Y:	return 3;
   1214 		case CUBEFACE_POSITIVE_Z:	return 4;
   1215 		case CUBEFACE_NEGATIVE_Z:	return 5;
   1216 
   1217 		default:
   1218 			return -1;
   1219 	}
   1220 }
   1221 
   1222 deUint32 packRGB999E5 (const tcu::Vec4& color)
   1223 {
   1224 	const int	mBits	= 9;
   1225 	const int	eBits	= 5;
   1226 	const int	eBias	= 15;
   1227 	const int	eMax	= (1<<eBits)-1;
   1228 	const float	maxVal	= (float)(((1<<mBits) - 1) * (1<<(eMax-eBias))) / (float)(1<<mBits);
   1229 
   1230 	float	rc		= deFloatClamp(color[0], 0.0f, maxVal);
   1231 	float	gc		= deFloatClamp(color[1], 0.0f, maxVal);
   1232 	float	bc		= deFloatClamp(color[2], 0.0f, maxVal);
   1233 	float	maxc	= de::max(rc, de::max(gc, bc));
   1234 	int		expp	= de::max(-eBias - 1, deFloorFloatToInt32(deFloatLog2(maxc))) + 1 + eBias;
   1235 	float	e		= deFloatPow(2.0f, (float)(expp-eBias-mBits));
   1236 	int		maxs	= deFloorFloatToInt32(maxc / e + 0.5f);
   1237 
   1238 	deUint32	exps	= maxs == (1<<mBits) ? expp+1 : expp;
   1239 	deUint32	rs		= (deUint32)deClamp32(deFloorFloatToInt32(rc / e + 0.5f), 0, (1<<9)-1);
   1240 	deUint32	gs		= (deUint32)deClamp32(deFloorFloatToInt32(gc / e + 0.5f), 0, (1<<9)-1);
   1241 	deUint32	bs		= (deUint32)deClamp32(deFloorFloatToInt32(bc / e + 0.5f), 0, (1<<9)-1);
   1242 
   1243 	DE_ASSERT((exps & ~((1<<5)-1)) == 0);
   1244 	DE_ASSERT((rs & ~((1<<9)-1)) == 0);
   1245 	DE_ASSERT((gs & ~((1<<9)-1)) == 0);
   1246 	DE_ASSERT((bs & ~((1<<9)-1)) == 0);
   1247 
   1248 	return rs | (gs << 9) | (bs << 18) | (exps << 27);
   1249 }
   1250 
   1251 // Sampler utils
   1252 
   1253 static const void* addOffset (const void* ptr, int numBytes)
   1254 {
   1255 	return (const deUint8*)ptr + numBytes;
   1256 }
   1257 
   1258 static void* addOffset (void* ptr, int numBytes)
   1259 {
   1260 	return (deUint8*)ptr + numBytes;
   1261 }
   1262 
   1263 template <typename AccessType>
   1264 static AccessType toSamplerAccess (const AccessType& baseAccess, Sampler::DepthStencilMode mode)
   1265 {
   1266 	// make sure to update this if type table is updated
   1267 	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40);
   1268 
   1269 	if (!isCombinedDepthStencilType(baseAccess.getFormat().type))
   1270 		return baseAccess;
   1271 	else
   1272 	{
   1273 #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
   1274 		const deUint32 uint32ByteOffsetBits0To8		= 0; //!< least significant byte in the lowest address
   1275 		const deUint32 uint32ByteOffsetBits0To24	= 0;
   1276 		const deUint32 uint32ByteOffsetBits8To32	= 1;
   1277 		const deUint32 uint32ByteOffsetBits16To32	= 2;
   1278 		const deUint32 uint32ByteOffsetBits24To32	= 3;
   1279 #else
   1280 		const deUint32 uint32ByteOffsetBits0To8		= 3; //!< least significant byte in the highest address
   1281 		const deUint32 uint32ByteOffsetBits0To24	= 1;
   1282 		const deUint32 uint32ByteOffsetBits8To32	= 0;
   1283 		const deUint32 uint32ByteOffsetBits16To32	= 0;
   1284 		const deUint32 uint32ByteOffsetBits24To32	= 0;
   1285 #endif
   1286 
   1287 		// Sampled channel must exist
   1288 		DE_ASSERT(baseAccess.getFormat().order == TextureFormat::DS ||
   1289 				  (mode == Sampler::MODE_DEPTH && baseAccess.getFormat().order == TextureFormat::D) ||
   1290 				  (mode == Sampler::MODE_STENCIL && baseAccess.getFormat().order == TextureFormat::S));
   1291 
   1292 		// combined formats have multiple channel classes, detect on sampler settings
   1293 		switch (baseAccess.getFormat().type)
   1294 		{
   1295 			case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
   1296 			{
   1297 				if (mode == Sampler::MODE_DEPTH)
   1298 				{
   1299 					// select the float component
   1300 					return AccessType(TextureFormat(TextureFormat::D, TextureFormat::FLOAT),
   1301 									  baseAccess.getSize(),
   1302 									  baseAccess.getPitch(),
   1303 									  baseAccess.getDataPtr());
   1304 				}
   1305 				else if (mode == Sampler::MODE_STENCIL)
   1306 				{
   1307 					// select the uint 8 component
   1308 					return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8),
   1309 									  baseAccess.getSize(),
   1310 									  baseAccess.getPitch(),
   1311 									  addOffset(baseAccess.getDataPtr(), 4 + uint32ByteOffsetBits0To8));
   1312 				}
   1313 				else
   1314 				{
   1315 					// unknown sampler mode
   1316 					DE_ASSERT(false);
   1317 					return AccessType();
   1318 				}
   1319 			}
   1320 
   1321 			case TextureFormat::UNSIGNED_INT_16_8_8:
   1322 			{
   1323 				if (mode == Sampler::MODE_DEPTH)
   1324 				{
   1325 					// select the unorm16 component
   1326 					return AccessType(TextureFormat(TextureFormat::D, TextureFormat::UNORM_INT16),
   1327 									  baseAccess.getSize(),
   1328 									  baseAccess.getPitch(),
   1329 									  addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits16To32));
   1330 				}
   1331 				else if (mode == Sampler::MODE_STENCIL)
   1332 				{
   1333 					// select the uint 8 component
   1334 					return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8),
   1335 									  baseAccess.getSize(),
   1336 									  baseAccess.getPitch(),
   1337 									  addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits0To8));
   1338 				}
   1339 				else
   1340 				{
   1341 					// unknown sampler mode
   1342 					DE_ASSERT(false);
   1343 					return AccessType();
   1344 				}
   1345 			}
   1346 
   1347 			case TextureFormat::UNSIGNED_INT_24_8:
   1348 			{
   1349 				if (mode == Sampler::MODE_DEPTH)
   1350 				{
   1351 					// select the unorm24 component
   1352 					return AccessType(TextureFormat(TextureFormat::D, TextureFormat::UNORM_INT24),
   1353 									  baseAccess.getSize(),
   1354 									  baseAccess.getPitch(),
   1355 									  addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits8To32));
   1356 				}
   1357 				else if (mode == Sampler::MODE_STENCIL)
   1358 				{
   1359 					// select the uint 8 component
   1360 					return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8),
   1361 									  baseAccess.getSize(),
   1362 									  baseAccess.getPitch(),
   1363 									  addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits0To8));
   1364 				}
   1365 				else
   1366 				{
   1367 					// unknown sampler mode
   1368 					DE_ASSERT(false);
   1369 					return AccessType();
   1370 				}
   1371 			}
   1372 
   1373 			case TextureFormat::UNSIGNED_INT_24_8_REV:
   1374 			{
   1375 				if (mode == Sampler::MODE_DEPTH)
   1376 				{
   1377 					// select the unorm24 component
   1378 					return AccessType(TextureFormat(TextureFormat::D, TextureFormat::UNORM_INT24),
   1379 									  baseAccess.getSize(),
   1380 									  baseAccess.getPitch(),
   1381 									  addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits0To24));
   1382 				}
   1383 				else if (mode == Sampler::MODE_STENCIL)
   1384 				{
   1385 					// select the uint 8 component
   1386 					return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8),
   1387 									  baseAccess.getSize(),
   1388 									  baseAccess.getPitch(),
   1389 									  addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits24To32));
   1390 				}
   1391 				else
   1392 				{
   1393 					// unknown sampler mode
   1394 					DE_ASSERT(false);
   1395 					return AccessType();
   1396 				}
   1397 			}
   1398 
   1399 			default:
   1400 			{
   1401 				// unknown combined format
   1402 				DE_ASSERT(false);
   1403 				return AccessType();
   1404 			}
   1405 		}
   1406 	}
   1407 }
   1408 
   1409 PixelBufferAccess getEffectiveDepthStencilAccess (const PixelBufferAccess& baseAccess, Sampler::DepthStencilMode mode)
   1410 {
   1411 	return toSamplerAccess<PixelBufferAccess>(baseAccess, mode);
   1412 }
   1413 
   1414 ConstPixelBufferAccess getEffectiveDepthStencilAccess (const ConstPixelBufferAccess& baseAccess, Sampler::DepthStencilMode mode)
   1415 {
   1416 	return toSamplerAccess<ConstPixelBufferAccess>(baseAccess, mode);
   1417 }
   1418 
   1419 TextureFormat getEffectiveDepthStencilTextureFormat (const TextureFormat& baseFormat, Sampler::DepthStencilMode mode)
   1420 {
   1421 	return toSamplerAccess(ConstPixelBufferAccess(baseFormat, IVec3(0, 0, 0), DE_NULL), mode).getFormat();
   1422 }
   1423 
   1424 template <typename ViewType>
   1425 ViewType getEffectiveTView (const ViewType& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
   1426 {
   1427 	storage.resize(src.getNumLevels());
   1428 
   1429 	ViewType view = ViewType(src.getNumLevels(), &storage[0]);
   1430 
   1431 	for (int levelNdx = 0; levelNdx < src.getNumLevels(); ++levelNdx)
   1432 		storage[levelNdx] = tcu::getEffectiveDepthStencilAccess(src.getLevel(levelNdx), sampler.depthStencilMode);
   1433 
   1434 	return view;
   1435 }
   1436 
   1437 tcu::TextureCubeView getEffectiveTView (const tcu::TextureCubeView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
   1438 {
   1439 	storage.resize(tcu::CUBEFACE_LAST * src.getNumLevels());
   1440 
   1441 	const tcu::ConstPixelBufferAccess* storagePtrs[tcu::CUBEFACE_LAST] =
   1442 	{
   1443 		&storage[0 * src.getNumLevels()],
   1444 		&storage[1 * src.getNumLevels()],
   1445 		&storage[2 * src.getNumLevels()],
   1446 		&storage[3 * src.getNumLevels()],
   1447 		&storage[4 * src.getNumLevels()],
   1448 		&storage[5 * src.getNumLevels()],
   1449 	};
   1450 
   1451 	tcu::TextureCubeView view = tcu::TextureCubeView(src.getNumLevels(), storagePtrs);
   1452 
   1453 	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
   1454 	for (int levelNdx = 0; levelNdx < src.getNumLevels(); ++levelNdx)
   1455 		storage[faceNdx * src.getNumLevels() + levelNdx] = tcu::getEffectiveDepthStencilAccess(src.getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), sampler.depthStencilMode);
   1456 
   1457 	return view;
   1458 }
   1459 
   1460 tcu::Texture1DView getEffectiveTextureView (const tcu::Texture1DView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
   1461 {
   1462 	return getEffectiveTView(src, storage, sampler);
   1463 }
   1464 
   1465 tcu::Texture2DView getEffectiveTextureView (const tcu::Texture2DView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
   1466 {
   1467 	return getEffectiveTView(src, storage, sampler);
   1468 }
   1469 
   1470 tcu::Texture3DView getEffectiveTextureView (const tcu::Texture3DView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
   1471 {
   1472 	return getEffectiveTView(src, storage, sampler);
   1473 }
   1474 
   1475 tcu::Texture1DArrayView getEffectiveTextureView (const tcu::Texture1DArrayView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
   1476 {
   1477 	return getEffectiveTView(src, storage, sampler);
   1478 }
   1479 
   1480 tcu::Texture2DArrayView getEffectiveTextureView (const tcu::Texture2DArrayView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
   1481 {
   1482 	return getEffectiveTView(src, storage, sampler);
   1483 }
   1484 
   1485 tcu::TextureCubeView getEffectiveTextureView (const tcu::TextureCubeView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
   1486 {
   1487 	return getEffectiveTView(src, storage, sampler);
   1488 }
   1489 
   1490 tcu::TextureCubeArrayView getEffectiveTextureView (const tcu::TextureCubeArrayView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
   1491 {
   1492 	return getEffectiveTView(src, storage, sampler);
   1493 }
   1494 
   1495 //! Returns the effective swizzle of a border color. The effective swizzle is the
   1496 //! equal to first writing an RGBA color with a write swizzle and then reading
   1497 //! it back using a read swizzle, i.e. BorderSwizzle(c) == readSwizzle(writeSwizzle(C))
   1498 static const TextureSwizzle& getBorderColorReadSwizzle (TextureFormat::ChannelOrder order)
   1499 {
   1500 	// make sure to update these tables when channel orders are updated
   1501 	DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 21);
   1502 
   1503 	static const TextureSwizzle INV		= {{ TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ONE	}};
   1504 	static const TextureSwizzle R		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ONE	}};
   1505 	static const TextureSwizzle A		= {{ TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_3	}};
   1506 	static const TextureSwizzle I		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0	}};
   1507 	static const TextureSwizzle L		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_ONE	}};
   1508 	static const TextureSwizzle LA		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_3	}};
   1509 	static const TextureSwizzle RG		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ONE	}};
   1510 	static const TextureSwizzle RA		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_3	}};
   1511 	static const TextureSwizzle RGB		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_2,		TextureSwizzle::CHANNEL_ONE	}};
   1512 	static const TextureSwizzle RGBA	= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_2,		TextureSwizzle::CHANNEL_3	}};
   1513 	static const TextureSwizzle D		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ONE	}};
   1514 	static const TextureSwizzle S		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ONE	}};
   1515 
   1516 	const TextureSwizzle* swizzle;
   1517 
   1518 	switch (order)
   1519 	{
   1520 		case TextureFormat::R:			swizzle = &R;		break;
   1521 		case TextureFormat::A:			swizzle = &A;		break;
   1522 		case TextureFormat::I:			swizzle = &I;		break;
   1523 		case TextureFormat::L:			swizzle = &L;		break;
   1524 		case TextureFormat::LA:			swizzle = &LA;		break;
   1525 		case TextureFormat::RG:			swizzle = &RG;		break;
   1526 		case TextureFormat::RA:			swizzle = &RA;		break;
   1527 		case TextureFormat::RGB:		swizzle = &RGB;		break;
   1528 		case TextureFormat::RGBA:		swizzle = &RGBA;	break;
   1529 		case TextureFormat::ARGB:		swizzle = &RGBA;	break;
   1530 		case TextureFormat::BGR:		swizzle = &RGB;		break;
   1531 		case TextureFormat::BGRA:		swizzle = &RGBA;	break;
   1532 		case TextureFormat::sR:			swizzle = &R;		break;
   1533 		case TextureFormat::sRG:		swizzle = &RG;		break;
   1534 		case TextureFormat::sRGB:		swizzle = &RGB;		break;
   1535 		case TextureFormat::sRGBA:		swizzle = &RGBA;	break;
   1536 		case TextureFormat::sBGR:		swizzle = &RGB;		break;
   1537 		case TextureFormat::sBGRA:		swizzle = &RGBA;	break;
   1538 		case TextureFormat::D:			swizzle = &D;		break;
   1539 		case TextureFormat::S:			swizzle = &S;		break;
   1540 
   1541 		case TextureFormat::DS:
   1542 			DE_ASSERT(false); // combined depth-stencil border color?
   1543 			swizzle = &INV;
   1544 			break;
   1545 
   1546 		default:
   1547 			DE_ASSERT(false);
   1548 			swizzle = &INV;
   1549 			break;
   1550 	}
   1551 
   1552 #ifdef DE_DEBUG
   1553 
   1554 	{
   1555 		// check that BorderSwizzle(c) == readSwizzle(writeSwizzle(C))
   1556 		const TextureSwizzle& readSwizzle	= getChannelReadSwizzle(order);
   1557 		const TextureSwizzle& writeSwizzle	= getChannelWriteSwizzle(order);
   1558 
   1559 		for (int ndx = 0; ndx < 4; ++ndx)
   1560 		{
   1561 			TextureSwizzle::Channel writeRead = readSwizzle.components[ndx];
   1562 			if (deInRange32(writeRead, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE)
   1563 				writeRead = writeSwizzle.components[(int)writeRead];
   1564 			DE_ASSERT(writeRead == swizzle->components[ndx]);
   1565 		}
   1566 	}
   1567 
   1568 #endif
   1569 
   1570 	return *swizzle;
   1571 }
   1572 
   1573 static tcu::UVec4 getNBitUnsignedIntegerVec4MaxValue (const tcu::IVec4& numBits)
   1574 {
   1575 	return tcu::UVec4((numBits[0] > 0) ? (deUintMaxValue32(numBits[0])) : (0),
   1576 					  (numBits[1] > 0) ? (deUintMaxValue32(numBits[1])) : (0),
   1577 					  (numBits[2] > 0) ? (deUintMaxValue32(numBits[2])) : (0),
   1578 					  (numBits[3] > 0) ? (deUintMaxValue32(numBits[3])) : (0));
   1579 }
   1580 
   1581 static tcu::IVec4 getNBitSignedIntegerVec4MaxValue (const tcu::IVec4& numBits)
   1582 {
   1583 	return tcu::IVec4((numBits[0] > 0) ? (deIntMaxValue32(numBits[0])) : (0),
   1584 					  (numBits[1] > 0) ? (deIntMaxValue32(numBits[1])) : (0),
   1585 					  (numBits[2] > 0) ? (deIntMaxValue32(numBits[2])) : (0),
   1586 					  (numBits[3] > 0) ? (deIntMaxValue32(numBits[3])) : (0));
   1587 }
   1588 
   1589 static tcu::IVec4 getNBitSignedIntegerVec4MinValue (const tcu::IVec4& numBits)
   1590 {
   1591 	return tcu::IVec4((numBits[0] > 0) ? (deIntMinValue32(numBits[0])) : (0),
   1592 					  (numBits[1] > 0) ? (deIntMinValue32(numBits[1])) : (0),
   1593 					  (numBits[2] > 0) ? (deIntMinValue32(numBits[2])) : (0),
   1594 					  (numBits[3] > 0) ? (deIntMinValue32(numBits[3])) : (0));
   1595 }
   1596 
   1597 static tcu::Vec4 getTextureBorderColorFloat (const TextureFormat& format, const Sampler& sampler)
   1598 {
   1599 	const tcu::TextureChannelClass	channelClass	= getTextureChannelClass(format.type);
   1600 	const TextureSwizzle::Channel*	channelMap		= getBorderColorReadSwizzle(format.order).components;
   1601 	const bool						isFloat			= channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT;
   1602 	const bool						isSigned		= channelClass != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
   1603 	const float						valueMin		= (isSigned) ? (-1.0f) : (0.0f);
   1604 	const float						valueMax		= 1.0f;
   1605 	Vec4							result;
   1606 
   1607 	DE_ASSERT(channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT ||
   1608 			  channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ||
   1609 			  channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT);
   1610 
   1611 	for (int c = 0; c < 4; c++)
   1612 	{
   1613 		const TextureSwizzle::Channel map = channelMap[c];
   1614 		if (map == TextureSwizzle::CHANNEL_ZERO)
   1615 			result[c] = 0.0f;
   1616 		else if (map == TextureSwizzle::CHANNEL_ONE)
   1617 			result[c] = 1.0f;
   1618 		else if (isFloat)
   1619 		{
   1620 			// floating point values are not clamped
   1621 			result[c] = sampler.borderColor.getAccess<float>()[(int)map];
   1622 		}
   1623 		else
   1624 		{
   1625 			// fixed point values are clamped to a representable range
   1626 			result[c] = de::clamp(sampler.borderColor.getAccess<float>()[(int)map], valueMin, valueMax);
   1627 		}
   1628 	}
   1629 
   1630 	return result;
   1631 }
   1632 
   1633 static tcu::IVec4 getTextureBorderColorInt (const TextureFormat& format, const Sampler& sampler)
   1634 {
   1635 	const tcu::TextureChannelClass	channelClass	= getTextureChannelClass(format.type);
   1636 	const TextureSwizzle::Channel*	channelMap		= getBorderColorReadSwizzle(format.order).components;
   1637 	const IVec4						channelBits		= getChannelBitDepth(format.type);
   1638 	const IVec4						valueMin		= getNBitSignedIntegerVec4MinValue(channelBits);
   1639 	const IVec4						valueMax		= getNBitSignedIntegerVec4MaxValue(channelBits);
   1640 	IVec4							result;
   1641 
   1642 	DE_ASSERT(channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
   1643 	DE_UNREF(channelClass);
   1644 
   1645 	for (int c = 0; c < 4; c++)
   1646 	{
   1647 		const TextureSwizzle::Channel map = channelMap[c];
   1648 		if (map == TextureSwizzle::CHANNEL_ZERO)
   1649 			result[c] = 0;
   1650 		else if (map == TextureSwizzle::CHANNEL_ONE)
   1651 			result[c] = 1;
   1652 		else
   1653 		{
   1654 			// integer values are clamped to a representable range
   1655 			result[c] = de::clamp(sampler.borderColor.getAccess<deInt32>()[(int)map], valueMin[(int)map], valueMax[(int)map]);
   1656 		}
   1657 	}
   1658 
   1659 	return result;
   1660 }
   1661 
   1662 static tcu::UVec4 getTextureBorderColorUint (const TextureFormat& format, const Sampler& sampler)
   1663 {
   1664 	const tcu::TextureChannelClass	channelClass	= getTextureChannelClass(format.type);
   1665 	const TextureSwizzle::Channel*	channelMap		= getBorderColorReadSwizzle(format.order).components;
   1666 	const IVec4						channelBits		= getChannelBitDepth(format.type);
   1667 	const UVec4						valueMax		= getNBitUnsignedIntegerVec4MaxValue(channelBits);
   1668 	UVec4							result;
   1669 
   1670 	DE_ASSERT(channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
   1671 	DE_UNREF(channelClass);
   1672 
   1673 	for (int c = 0; c < 4; c++)
   1674 	{
   1675 		const TextureSwizzle::Channel map = channelMap[c];
   1676 		if (map == TextureSwizzle::CHANNEL_ZERO)
   1677 			result[c] = 0;
   1678 		else if (map == TextureSwizzle::CHANNEL_ONE)
   1679 			result[c] = 1;
   1680 		else
   1681 		{
   1682 			// integer values are clamped to a representable range
   1683 			result[c] = de::min(sampler.borderColor.getAccess<deUint32>()[(int)map], valueMax[(int)map]);
   1684 		}
   1685 	}
   1686 
   1687 	return result;
   1688 }
   1689 
   1690 template <typename ScalarType>
   1691 tcu::Vector<ScalarType, 4> sampleTextureBorder (const TextureFormat& format, const Sampler& sampler)
   1692 {
   1693 	const tcu::TextureChannelClass channelClass = getTextureChannelClass(format.type);
   1694 
   1695 	switch (channelClass)
   1696 	{
   1697 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
   1698 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
   1699 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
   1700 			return getTextureBorderColorFloat(format, sampler).cast<ScalarType>();
   1701 
   1702 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
   1703 			return getTextureBorderColorInt(format, sampler).cast<ScalarType>();
   1704 
   1705 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
   1706 			return getTextureBorderColorUint(format, sampler).cast<ScalarType>();
   1707 
   1708 		default:
   1709 			DE_ASSERT(false);
   1710 			return tcu::Vector<ScalarType, 4>();
   1711 	}
   1712 }
   1713 
   1714 // instantiation
   1715 template tcu::Vector<float, 4>		sampleTextureBorder (const TextureFormat& format, const Sampler& sampler);
   1716 template tcu::Vector<deInt32, 4>	sampleTextureBorder (const TextureFormat& format, const Sampler& sampler);
   1717 template tcu::Vector<deUint32, 4>	sampleTextureBorder (const TextureFormat& format, const Sampler& sampler);
   1718 
   1719 } // tcu
   1720