• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
linearToSRGBIfNeeded(const TextureFormat & format,const tcu::Vec4 & color)115 tcu::Vec4 linearToSRGBIfNeeded (const TextureFormat& format, const tcu::Vec4& color)
116 {
117 	return isSRGB(format) ? linearToSRGB(color) : color;
118 }
119 
isCombinedDepthStencilType(TextureFormat::ChannelType type)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 
hasStencilComponent(TextureFormat::ChannelOrder order)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 
hasDepthComponent(TextureFormat::ChannelOrder order)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
getTextureChannelClass(TextureFormat::ChannelType channelType)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 
isAccessValid(TextureFormat format,TextureAccessType type)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  *//*--------------------------------------------------------------------*/
getSubregion(const ConstPixelBufferAccess & access,int x,int y,int z,int width,int height,int depth)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  *//*--------------------------------------------------------------------*/
getSubregion(const PixelBufferAccess & access,int x,int y,int z,int width,int height,int depth)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  *//*--------------------------------------------------------------------*/
getSubregion(const PixelBufferAccess & access,int x,int y,int width,int height)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  *//*--------------------------------------------------------------------*/
getSubregion(const ConstPixelBufferAccess & access,int x,int y,int width,int height)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  *//*--------------------------------------------------------------------*/
flipYAccess(const PixelBufferAccess & access)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  *//*--------------------------------------------------------------------*/
flipYAccess(const ConstPixelBufferAccess & access)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 
getFloatChannelValueRange(TextureFormat::ChannelType channelType)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 = -2147483648.0f;	cMax = 2147483647.0f;	break;
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 = 4294967295.f;	break;
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  *//*--------------------------------------------------------------------*/
getTextureFormatInfo(const TextureFormat & format)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 
getFormatMinIntValue(const TextureFormat & format)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 
getFormatMaxIntValue(const TextureFormat & format)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 
getFormatMaxUintValue(const TextureFormat & format)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 
getChannelBitDepth(TextureFormat::ChannelType channelType)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 
getTextureFormatBitDepth(const TextureFormat & format)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 
getChannelMantissaBitDepth(TextureFormat::ChannelType channelType)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 
getTextureFormatMantissaBitDepth(const TextureFormat & format)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 
getTextureFormatChannelMask(const TextureFormat & format)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 
linearInterpolate(float t,float minVal,float maxVal)667 static inline float linearInterpolate (float t, float minVal, float maxVal)
668 {
669 	return minVal + (maxVal - minVal) * t;
670 }
671 
linearInterpolate(float t,const Vec4 & a,const Vec4 & b)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 
fillRow(const PixelBufferAccess & dst,int y,int z,int pixelSize,const deUint8 * pixel)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 
clear(const PixelBufferAccess & access,const Vec4 & color)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 
clear(const PixelBufferAccess & access,const IVec4 & color)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 
clear(const PixelBufferAccess & access,const UVec4 & color)776 void clear (const PixelBufferAccess& access, const UVec4& color)
777 {
778 	clear(access, color.cast<deInt32>());
779 }
780 
clearDepth(const PixelBufferAccess & access,float depth)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 
clearStencil(const PixelBufferAccess & access,int stencil)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 
fillWithComponentGradients1D(const PixelBufferAccess & access,const Vec4 & minVal,const Vec4 & maxVal)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 
fillWithComponentGradients2D(const PixelBufferAccess & access,const Vec4 & minVal,const Vec4 & maxVal)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 
fillWithComponentGradients3D(const PixelBufferAccess & dst,const Vec4 & minVal,const Vec4 & maxVal)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 
fillWithComponentGradients(const PixelBufferAccess & access,const Vec4 & minVal,const Vec4 & maxVal)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 
fillWithGrid1D(const PixelBufferAccess & access,int cellSize,const Vec4 & colorA,const Vec4 & colorB)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 
fillWithGrid2D(const PixelBufferAccess & access,int cellSize,const Vec4 & colorA,const Vec4 & colorB)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 
fillWithGrid3D(const PixelBufferAccess & access,int cellSize,const Vec4 & colorA,const Vec4 & colorB)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 
fillWithGrid(const PixelBufferAccess & access,int cellSize,const Vec4 & colorA,const Vec4 & colorB)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 
fillWithRepeatableGradient(const PixelBufferAccess & access,const Vec4 & colorA,const Vec4 & colorB)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 
fillWithRGBAQuads(const PixelBufferAccess & dst)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.
fillWithMetaballs(const PixelBufferAccess & dst,int numBalls,deUint32 seed)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 
copy(const PixelBufferAccess & dst,const ConstPixelBufferAccess & src)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 
scale(const PixelBufferAccess & dst,const ConstPixelBufferAccess & src,Sampler::FilterMode filter)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 
estimatePixelValueRange(const ConstPixelBufferAccess & access,Vec4 & minVal,Vec4 & maxVal)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 
computePixelScaleBias(const ConstPixelBufferAccess & access,Vec4 & scale,Vec4 & bias)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 
getCubeArrayFaceIndex(CubeFace face)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 
packRGB999E5(const tcu::Vec4 & color)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 
addOffset(const void * ptr,int numBytes)1253 static const void* addOffset (const void* ptr, int numBytes)
1254 {
1255 	return (const deUint8*)ptr + numBytes;
1256 }
1257 
addOffset(void * ptr,int numBytes)1258 static void* addOffset (void* ptr, int numBytes)
1259 {
1260 	return (deUint8*)ptr + numBytes;
1261 }
1262 
1263 template <typename AccessType>
toSamplerAccess(const AccessType & baseAccess,Sampler::DepthStencilMode mode)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 
getEffectiveDepthStencilAccess(const PixelBufferAccess & baseAccess,Sampler::DepthStencilMode mode)1409 PixelBufferAccess getEffectiveDepthStencilAccess (const PixelBufferAccess& baseAccess, Sampler::DepthStencilMode mode)
1410 {
1411 	return toSamplerAccess<PixelBufferAccess>(baseAccess, mode);
1412 }
1413 
getEffectiveDepthStencilAccess(const ConstPixelBufferAccess & baseAccess,Sampler::DepthStencilMode mode)1414 ConstPixelBufferAccess getEffectiveDepthStencilAccess (const ConstPixelBufferAccess& baseAccess, Sampler::DepthStencilMode mode)
1415 {
1416 	return toSamplerAccess<ConstPixelBufferAccess>(baseAccess, mode);
1417 }
1418 
getEffectiveDepthStencilTextureFormat(const TextureFormat & baseFormat,Sampler::DepthStencilMode mode)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>
getEffectiveTView(const ViewType & src,std::vector<tcu::ConstPixelBufferAccess> & storage,const tcu::Sampler & sampler)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 
getEffectiveTView(const tcu::TextureCubeView & src,std::vector<tcu::ConstPixelBufferAccess> & storage,const tcu::Sampler & sampler)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 
getEffectiveTextureView(const tcu::Texture1DView & src,std::vector<tcu::ConstPixelBufferAccess> & storage,const tcu::Sampler & sampler)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 
getEffectiveTextureView(const tcu::Texture2DView & src,std::vector<tcu::ConstPixelBufferAccess> & storage,const tcu::Sampler & sampler)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 
getEffectiveTextureView(const tcu::Texture3DView & src,std::vector<tcu::ConstPixelBufferAccess> & storage,const tcu::Sampler & sampler)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 
getEffectiveTextureView(const tcu::Texture1DArrayView & src,std::vector<tcu::ConstPixelBufferAccess> & storage,const tcu::Sampler & sampler)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 
getEffectiveTextureView(const tcu::Texture2DArrayView & src,std::vector<tcu::ConstPixelBufferAccess> & storage,const tcu::Sampler & sampler)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 
getEffectiveTextureView(const tcu::TextureCubeView & src,std::vector<tcu::ConstPixelBufferAccess> & storage,const tcu::Sampler & sampler)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 
getEffectiveTextureView(const tcu::TextureCubeArrayView & src,std::vector<tcu::ConstPixelBufferAccess> & storage,const tcu::Sampler & sampler)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))
getBorderColorReadSwizzle(TextureFormat::ChannelOrder order)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 
getNBitUnsignedIntegerVec4MaxValue(const tcu::IVec4 & numBits)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 
getNBitSignedIntegerVec4MaxValue(const tcu::IVec4 & numBits)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 
getNBitSignedIntegerVec4MinValue(const tcu::IVec4 & numBits)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 
getTextureBorderColorFloat(const TextureFormat & format,const Sampler & sampler)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 
getTextureBorderColorInt(const TextureFormat & format,const Sampler & sampler)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 
getTextureBorderColorUint(const TextureFormat & format,const Sampler & sampler)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>
sampleTextureBorder(const TextureFormat & format,const Sampler & sampler)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