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