1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Texture utilities.
22 *//*--------------------------------------------------------------------*/
24 #include "tcuTextureUtil.hpp"
25 #include "tcuVectorUtil.hpp"
26 #include "deRandom.hpp"
35 static inline float sRGBChannelToLinear (float cs)
40 return deFloatPow((cs + 0.055f) / 1.055f, 2.4f);
43 static const deUint32 s_srgb8Lut[256] =
45 #include "tcuSRGB8Lut.inl"
48 static inline float sRGB8ChannelToLinear (deUint32 cs)
52 // \note This triggers UB, but in practice it doesn't cause any problems
53 return ((const float*)s_srgb8Lut)[cs];
56 static inline float linearChannelToSRGB (float cl)
60 else if (cl < 0.0031308f)
63 return 1.055f*deFloatPow(cl, 0.41666f) - 0.055f;
68 //! Convert sRGB to linear colorspace
69 Vec4 sRGBToLinear (const Vec4& cs)
71 return Vec4(sRGBChannelToLinear(cs[0]),
72 sRGBChannelToLinear(cs[1]),
73 sRGBChannelToLinear(cs[2]),
77 Vec4 sRGB8ToLinear (const UVec4& cs)
79 return Vec4(sRGB8ChannelToLinear(cs[0]),
80 sRGB8ChannelToLinear(cs[1]),
81 sRGB8ChannelToLinear(cs[2]),
85 Vec4 sRGBA8ToLinear (const UVec4& cs)
87 return Vec4(sRGB8ChannelToLinear(cs[0]),
88 sRGB8ChannelToLinear(cs[1]),
89 sRGB8ChannelToLinear(cs[2]),
90 (float)cs[3] / 255.0f);
93 //! Convert from linear to sRGB colorspace
94 Vec4 linearToSRGB (const Vec4& cl)
96 return Vec4(linearChannelToSRGB(cl[0]),
97 linearChannelToSRGB(cl[1]),
98 linearChannelToSRGB(cl[2]),
102 bool isSRGB (TextureFormat format)
104 // make sure to update this if type table is updated
105 DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 21);
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;
115 tcu::Vec4 linearToSRGBIfNeeded (const TextureFormat& format, const tcu::Vec4& color)
117 return isSRGB(format) ? linearToSRGB(color) : color;
120 bool isCombinedDepthStencilType (TextureFormat::ChannelType type)
122 // make sure to update this if type table is updated
123 DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 38);
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;
131 bool hasStencilComponent (TextureFormat::ChannelOrder order)
133 DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 21);
137 case TextureFormat::S:
138 case TextureFormat::DS:
146 bool hasDepthComponent (TextureFormat::ChannelOrder order)
148 DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 21);
152 case TextureFormat::D:
153 case TextureFormat::DS:
161 //! Get texture channel class for format
162 TextureChannelClass getTextureChannelClass (TextureFormat::ChannelType channelType)
164 // make sure this table is updated if format table is updated
165 DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 38);
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
208 DE_FATAL("Unknown channel type");
209 return TEXTURECHANNELCLASS_LAST;
213 bool isAccessValid (TextureFormat format, TextureAccessType type)
215 DE_ASSERT(isValid(format));
217 if (format.order == TextureFormat::DS)
219 // It is never allowed to access combined depth-stencil format with getPixel().
220 // Instead either getPixDepth() or getPixStencil(), or effective depth- or stencil-
221 // access must be used.
224 else if (format.order == TextureFormat::D)
225 return type == TEXTUREACCESSTYPE_FLOAT;
226 else if (format.order == TextureFormat::S)
227 return type == TEXTUREACCESSTYPE_UNSIGNED_INT;
230 // A few packed color formats have access type restrictions
231 if (format.type == TextureFormat::UNSIGNED_INT_11F_11F_10F_REV ||
232 format.type == TextureFormat::UNSIGNED_INT_999_E5_REV)
233 return type == TEXTUREACCESSTYPE_FLOAT;
239 /*--------------------------------------------------------------------*//*!
240 * \brief Get access to subregion of pixel buffer
241 * \param access Parent access object
246 * \param height Height
248 * \return Access object that targets given subregion of parent access object
249 *//*--------------------------------------------------------------------*/
250 ConstPixelBufferAccess getSubregion (const ConstPixelBufferAccess& access, int x, int y, int z, int width, int height, int depth)
252 DE_ASSERT(de::inBounds(x, 0, access.getWidth()));
253 DE_ASSERT(de::inRange(x+width, x+1, access.getWidth()));
255 DE_ASSERT(de::inBounds(y, 0, access.getHeight()));
256 DE_ASSERT(de::inRange(y+height, y+1, access.getHeight()));
258 DE_ASSERT(de::inBounds(z, 0, access.getDepth()));
259 DE_ASSERT(de::inRange(z+depth, z+1, access.getDepth()));
261 return ConstPixelBufferAccess(access.getFormat(), tcu::IVec3(width, height, depth), access.getPitch(),
262 (const deUint8*)access.getDataPtr() + access.getPixelPitch()*x + access.getRowPitch()*y + access.getSlicePitch()*z);
265 /*--------------------------------------------------------------------*//*!
266 * \brief Get access to subregion of pixel buffer
267 * \param access Parent access object
272 * \param height Height
274 * \return Access object that targets given subregion of parent access object
275 *//*--------------------------------------------------------------------*/
276 PixelBufferAccess getSubregion (const PixelBufferAccess& access, int x, int y, int z, int width, int height, int depth)
278 DE_ASSERT(de::inBounds(x, 0, access.getWidth()));
279 DE_ASSERT(de::inRange(x+width, x+1, access.getWidth()));
281 DE_ASSERT(de::inBounds(y, 0, access.getHeight()));
282 DE_ASSERT(de::inRange(y+height, y+1, access.getHeight()));
284 DE_ASSERT(de::inBounds(z, 0, access.getDepth()));
285 DE_ASSERT(de::inRange(z+depth, z+1, access.getDepth()));
287 return PixelBufferAccess(access.getFormat(), tcu::IVec3(width, height, depth), access.getPitch(),
288 (deUint8*)access.getDataPtr() + access.getPixelPitch()*x + access.getRowPitch()*y + access.getSlicePitch()*z);
291 /*--------------------------------------------------------------------*//*!
292 * \brief Get access to subregion of pixel buffer
293 * \param access Parent access object
297 * \param height Height
298 * \return Access object that targets given subregion of parent access object
299 *//*--------------------------------------------------------------------*/
300 PixelBufferAccess getSubregion (const PixelBufferAccess& access, int x, int y, int width, int height)
302 return getSubregion(access, x, y, 0, width, height, 1);
305 /*--------------------------------------------------------------------*//*!
306 * \brief Get access to subregion of pixel buffer
307 * \param access Parent access object
311 * \param height Height
312 * \return Access object that targets given subregion of parent access object
313 *//*--------------------------------------------------------------------*/
314 ConstPixelBufferAccess getSubregion (const ConstPixelBufferAccess& access, int x, int y, int width, int height)
316 return getSubregion(access, x, y, 0, width, height, 1);
319 /*--------------------------------------------------------------------*//*!
320 * \brief Flip rows in Y direction
321 * \param access Access object
322 * \return Modified access object where Y coordinates are reversed
323 *//*--------------------------------------------------------------------*/
324 PixelBufferAccess flipYAccess (const PixelBufferAccess& access)
326 const int rowPitch = access.getRowPitch();
327 const int offsetToLast = rowPitch*(access.getHeight()-1);
328 const tcu::IVec3 pitch (access.getPixelPitch(), -rowPitch, access.getSlicePitch());
330 return PixelBufferAccess(access.getFormat(), access.getSize(), pitch, (deUint8*)access.getDataPtr() + offsetToLast);
333 /*--------------------------------------------------------------------*//*!
334 * \brief Flip rows in Y direction
335 * \param access Access object
336 * \return Modified access object where Y coordinates are reversed
337 *//*--------------------------------------------------------------------*/
338 ConstPixelBufferAccess flipYAccess (const ConstPixelBufferAccess& access)
340 const int rowPitch = access.getRowPitch();
341 const int offsetToLast = rowPitch*(access.getHeight()-1);
342 const tcu::IVec3 pitch (access.getPixelPitch(), -rowPitch, access.getSlicePitch());
344 return ConstPixelBufferAccess(access.getFormat(), access.getSize(), pitch, (deUint8*)access.getDataPtr() + offsetToLast);
347 static Vec2 getFloatChannelValueRange (TextureFormat::ChannelType channelType)
349 // make sure this table is updated if format table is updated
350 DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 38);
357 // Signed normalized formats.
358 case TextureFormat::SNORM_INT8:
359 case TextureFormat::SNORM_INT16:
360 case TextureFormat::SNORM_INT32:
361 case TextureFormat::SNORM_INT_1010102_REV: cMin = -1.0f; cMax = 1.0f; break;
363 // Unsigned normalized formats.
364 case TextureFormat::UNORM_INT8:
365 case TextureFormat::UNORM_INT16:
366 case TextureFormat::UNORM_INT24:
367 case TextureFormat::UNORM_INT32:
368 case TextureFormat::UNORM_BYTE_44:
369 case TextureFormat::UNORM_SHORT_565:
370 case TextureFormat::UNORM_SHORT_555:
371 case TextureFormat::UNORM_SHORT_4444:
372 case TextureFormat::UNORM_SHORT_5551:
373 case TextureFormat::UNORM_SHORT_1555:
374 case TextureFormat::UNORM_INT_101010:
375 case TextureFormat::UNORM_INT_1010102_REV: cMin = 0.0f; cMax = 1.0f; break;
378 case TextureFormat::SIGNED_INT8: cMin = -128.0f; cMax = 127.0f; break;
379 case TextureFormat::SIGNED_INT16: cMin = -32768.0f; cMax = 32767.0f; break;
380 case TextureFormat::SIGNED_INT32: cMin = -2147483648.0f; cMax = 2147483647.0f; break;
381 case TextureFormat::UNSIGNED_INT8: cMin = 0.0f; cMax = 255.0f; break;
382 case TextureFormat::UNSIGNED_INT16: cMin = 0.0f; cMax = 65535.0f; break;
383 case TextureFormat::UNSIGNED_INT24: cMin = 0.0f; cMax = 16777215.0f; break;
384 case TextureFormat::UNSIGNED_INT32: cMin = 0.0f; cMax = 4294967295.f; break;
385 case TextureFormat::HALF_FLOAT: cMin = -1e3f; cMax = 1e3f; break;
386 case TextureFormat::FLOAT: cMin = -1e5f; cMax = 1e5f; break;
387 case TextureFormat::FLOAT64: cMin = -1e5f; cMax = 1e5f; break;
388 case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV: cMin = 0.0f; cMax = 1e4f; break;
389 case TextureFormat::UNSIGNED_INT_999_E5_REV: cMin = 0.0f; cMax = 1e5f; break;
390 case TextureFormat::UNSIGNED_BYTE_44: cMin = 0.0f; cMax = 15.f; break;
391 case TextureFormat::UNSIGNED_SHORT_4444: cMin = 0.0f; cMax = 15.f; break;
397 return Vec2(cMin, cMax);
400 /*--------------------------------------------------------------------*//*!
401 * \brief Get standard parameters for testing texture format
403 * Returns TextureFormatInfo that describes good parameters for exercising
404 * given TextureFormat. Parameters include value ranges per channel and
405 * suitable lookup scaling and bias in order to reduce result back to
407 *//*--------------------------------------------------------------------*/
408 TextureFormatInfo getTextureFormatInfo (const TextureFormat& format)
411 if (format.type == TextureFormat::UNSIGNED_INT_1010102_REV)
412 return TextureFormatInfo(Vec4( 0.0f, 0.0f, 0.0f, 0.0f),
413 Vec4( 1023.0f, 1023.0f, 1023.0f, 3.0f),
414 Vec4(1.0f/1023.f, 1.0f/1023.0f, 1.0f/1023.0f, 1.0f/3.0f),
415 Vec4( 0.0f, 0.0f, 0.0f, 0.0f));
416 if (format.type == TextureFormat::SIGNED_INT_1010102_REV)
417 return TextureFormatInfo(Vec4( -512.0f, -512.0f, -512.0f, -2.0f),
418 Vec4( 511.0f, 511.0f, 511.0f, 1.0f),
419 Vec4(1.0f/1023.f, 1.0f/1023.0f, 1.0f/1023.0f, 1.0f/3.0f),
420 Vec4( 0.5f, 0.5f, 0.5f, 0.5f));
421 else if (format.order == TextureFormat::D || format.order == TextureFormat::DS)
422 return TextureFormatInfo(Vec4(0.0f, 0.0f, 0.0f, 0.0f),
423 Vec4(1.0f, 1.0f, 1.0f, 0.0f),
424 Vec4(1.0f, 1.0f, 1.0f, 1.0f),
425 Vec4(0.0f, 0.0f, 0.0f, 0.0f)); // Depth / stencil formats.
426 else if (format == TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_SHORT_5551))
427 return TextureFormatInfo(Vec4(0.0f, 0.0f, 0.0f, 0.5f),
428 Vec4(1.0f, 1.0f, 1.0f, 1.5f),
429 Vec4(1.0f, 1.0f, 1.0f, 1.0f),
430 Vec4(0.0f, 0.0f, 0.0f, 0.0f));
431 else if (format.type == TextureFormat::UNSIGNED_SHORT_5551)
432 return TextureFormatInfo(Vec4( 0.0f, 0.0f, 0.0f, 0.0f),
433 Vec4( 31.0f, 31.0f, 31.0f, 1.0f),
434 Vec4(1.0f/31.f, 1.0f/31.0f, 1.0f/31.0f, 1.0f),
435 Vec4( 0.0f, 0.0f, 0.0f, 0.0f));
436 else if (format.type == TextureFormat::UNSIGNED_SHORT_565)
437 return TextureFormatInfo(Vec4( 0.0f, 0.0f, 0.0f, 0.0f),
438 Vec4( 31.0f, 63.0f, 31.0f, 0.0f),
439 Vec4(1.0f/31.f, 1.0f/63.0f, 1.0f/31.0f, 1.0f),
440 Vec4( 0.0f, 0.0f, 0.0f, 0.0f));
442 const Vec2 cRange = getFloatChannelValueRange(format.type);
443 const TextureSwizzle::Channel* map = getChannelReadSwizzle(format.order).components;
444 const BVec4 chnMask = BVec4(deInRange32(map[0], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
445 deInRange32(map[1], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
446 deInRange32(map[2], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
447 deInRange32(map[3], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE);
448 const float scale = 1.0f / (cRange[1] - cRange[0]);
449 const float bias = -cRange[0] * scale;
451 return TextureFormatInfo(select(cRange[0], 0.0f, chnMask),
452 select(cRange[1], 0.0f, chnMask),
453 select(scale, 1.0f, chnMask),
454 select(bias, 0.0f, chnMask));
457 IVec4 getFormatMinIntValue (const TextureFormat& format)
459 DE_ASSERT(getTextureChannelClass(format.type) == TEXTURECHANNELCLASS_SIGNED_INTEGER);
463 case TextureFormat::SIGNED_INT8: return IVec4(std::numeric_limits<deInt8>::min());
464 case TextureFormat::SIGNED_INT16: return IVec4(std::numeric_limits<deInt16>::min());
465 case TextureFormat::SIGNED_INT32: return IVec4(std::numeric_limits<deInt32>::min());
468 DE_FATAL("Invalid channel type");
473 IVec4 getFormatMaxIntValue (const TextureFormat& format)
475 DE_ASSERT(getTextureChannelClass(format.type) == TEXTURECHANNELCLASS_SIGNED_INTEGER);
477 if (format == TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT_1010102_REV) ||
478 format == TextureFormat(TextureFormat::BGRA, TextureFormat::SIGNED_INT_1010102_REV))
479 return IVec4(511, 511, 511, 1);
483 case TextureFormat::SIGNED_INT8: return IVec4(std::numeric_limits<deInt8>::max());
484 case TextureFormat::SIGNED_INT16: return IVec4(std::numeric_limits<deInt16>::max());
485 case TextureFormat::SIGNED_INT32: return IVec4(std::numeric_limits<deInt32>::max());
488 DE_FATAL("Invalid channel type");
493 UVec4 getFormatMaxUintValue (const TextureFormat& format)
495 DE_ASSERT(getTextureChannelClass(format.type) == TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
497 if (format == TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT_1010102_REV) ||
498 format == TextureFormat(TextureFormat::BGRA, TextureFormat::UNSIGNED_INT_1010102_REV))
499 return UVec4(1023u, 1023u, 1023u, 3u);
503 case TextureFormat::UNSIGNED_INT8: return UVec4(std::numeric_limits<deUint8>::max());
504 case TextureFormat::UNSIGNED_INT16: return UVec4(std::numeric_limits<deUint16>::max());
505 case TextureFormat::UNSIGNED_INT24: return UVec4(0xffffffu);
506 case TextureFormat::UNSIGNED_INT32: return UVec4(std::numeric_limits<deUint32>::max());
509 DE_FATAL("Invalid channel type");
514 static IVec4 getChannelBitDepth (TextureFormat::ChannelType channelType)
516 // make sure this table is updated if format table is updated
517 DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 38);
521 case TextureFormat::SNORM_INT8: return IVec4(8);
522 case TextureFormat::SNORM_INT16: return IVec4(16);
523 case TextureFormat::SNORM_INT32: return IVec4(32);
524 case TextureFormat::UNORM_INT8: return IVec4(8);
525 case TextureFormat::UNORM_INT16: return IVec4(16);
526 case TextureFormat::UNORM_INT24: return IVec4(24);
527 case TextureFormat::UNORM_INT32: return IVec4(32);
528 case TextureFormat::UNORM_BYTE_44: return IVec4(4,4,0,0);
529 case TextureFormat::UNORM_SHORT_565: return IVec4(5,6,5,0);
530 case TextureFormat::UNORM_SHORT_4444: return IVec4(4);
531 case TextureFormat::UNORM_SHORT_555: return IVec4(5,5,5,0);
532 case TextureFormat::UNORM_SHORT_5551: return IVec4(5,5,5,1);
533 case TextureFormat::UNORM_SHORT_1555: return IVec4(1,5,5,5);
534 case TextureFormat::UNSIGNED_BYTE_44: return IVec4(4,4,0,0);
535 case TextureFormat::UNSIGNED_SHORT_565: return IVec4(5,6,5,0);
536 case TextureFormat::UNSIGNED_SHORT_4444: return IVec4(4);
537 case TextureFormat::UNSIGNED_SHORT_5551: return IVec4(5,5,5,1);
538 case TextureFormat::UNORM_INT_101010: return IVec4(10,10,10,0);
539 case TextureFormat::SNORM_INT_1010102_REV: return IVec4(10,10,10,2);
540 case TextureFormat::UNORM_INT_1010102_REV: return IVec4(10,10,10,2);
541 case TextureFormat::SIGNED_INT8: return IVec4(8);
542 case TextureFormat::SIGNED_INT16: return IVec4(16);
543 case TextureFormat::SIGNED_INT32: return IVec4(32);
544 case TextureFormat::UNSIGNED_INT8: return IVec4(8);
545 case TextureFormat::UNSIGNED_INT16: return IVec4(16);
546 case TextureFormat::UNSIGNED_INT24: return IVec4(24);
547 case TextureFormat::UNSIGNED_INT32: return IVec4(32);
548 case TextureFormat::SIGNED_INT_1010102_REV: return IVec4(10,10,10,2);
549 case TextureFormat::UNSIGNED_INT_1010102_REV: return IVec4(10,10,10,2);
550 case TextureFormat::UNSIGNED_INT_16_8_8: return IVec4(16,8,0,0);
551 case TextureFormat::UNSIGNED_INT_24_8: return IVec4(24,8,0,0);
552 case TextureFormat::UNSIGNED_INT_24_8_REV: return IVec4(24,8,0,0);
553 case TextureFormat::HALF_FLOAT: return IVec4(16);
554 case TextureFormat::FLOAT: return IVec4(32);
555 case TextureFormat::FLOAT64: return IVec4(64);
556 case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV: return IVec4(11,11,10,0);
557 case TextureFormat::UNSIGNED_INT_999_E5_REV: return IVec4(9,9,9,0);
558 case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV: return IVec4(32,8,0,0);
565 IVec4 getTextureFormatBitDepth (const TextureFormat& format)
567 const IVec4 chnBits = getChannelBitDepth(format.type);
568 const TextureSwizzle::Channel* map = getChannelReadSwizzle(format.order).components;
569 const BVec4 chnMask = BVec4(deInRange32(map[0], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
570 deInRange32(map[1], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
571 deInRange32(map[2], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
572 deInRange32(map[3], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE);
573 const IVec4 chnSwz = IVec4((chnMask[0]) ? ((int)map[0]) : (0),
574 (chnMask[1]) ? ((int)map[1]) : (0),
575 (chnMask[2]) ? ((int)map[2]) : (0),
576 (chnMask[3]) ? ((int)map[3]) : (0));
578 return select(chnBits.swizzle(chnSwz.x(), chnSwz.y(), chnSwz.z(), chnSwz.w()), IVec4(0), chnMask);
581 static IVec4 getChannelMantissaBitDepth (TextureFormat::ChannelType channelType)
583 // make sure this table is updated if format table is updated
584 DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 38);
588 case TextureFormat::SNORM_INT8:
589 case TextureFormat::SNORM_INT16:
590 case TextureFormat::SNORM_INT32:
591 case TextureFormat::UNORM_INT8:
592 case TextureFormat::UNORM_INT16:
593 case TextureFormat::UNORM_INT24:
594 case TextureFormat::UNORM_INT32:
595 case TextureFormat::UNORM_BYTE_44:
596 case TextureFormat::UNORM_SHORT_565:
597 case TextureFormat::UNORM_SHORT_4444:
598 case TextureFormat::UNORM_SHORT_555:
599 case TextureFormat::UNORM_SHORT_5551:
600 case TextureFormat::UNORM_SHORT_1555:
601 case TextureFormat::UNSIGNED_BYTE_44:
602 case TextureFormat::UNSIGNED_SHORT_565:
603 case TextureFormat::UNSIGNED_SHORT_4444:
604 case TextureFormat::UNSIGNED_SHORT_5551:
605 case TextureFormat::UNORM_INT_101010:
606 case TextureFormat::SNORM_INT_1010102_REV:
607 case TextureFormat::UNORM_INT_1010102_REV:
608 case TextureFormat::SIGNED_INT8:
609 case TextureFormat::SIGNED_INT16:
610 case TextureFormat::SIGNED_INT32:
611 case TextureFormat::UNSIGNED_INT8:
612 case TextureFormat::UNSIGNED_INT16:
613 case TextureFormat::UNSIGNED_INT24:
614 case TextureFormat::UNSIGNED_INT32:
615 case TextureFormat::SIGNED_INT_1010102_REV:
616 case TextureFormat::UNSIGNED_INT_1010102_REV:
617 case TextureFormat::UNSIGNED_INT_16_8_8:
618 case TextureFormat::UNSIGNED_INT_24_8:
619 case TextureFormat::UNSIGNED_INT_24_8_REV:
620 case TextureFormat::UNSIGNED_INT_999_E5_REV:
621 return getChannelBitDepth(channelType);
623 case TextureFormat::HALF_FLOAT: return IVec4(10);
624 case TextureFormat::FLOAT: return IVec4(23);
625 case TextureFormat::FLOAT64: return IVec4(52);
626 case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV: return IVec4(6,6,5,0);
627 case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV: return IVec4(23,8,0,0);
634 IVec4 getTextureFormatMantissaBitDepth (const TextureFormat& format)
636 const IVec4 chnBits = getChannelMantissaBitDepth(format.type);
637 const TextureSwizzle::Channel* map = getChannelReadSwizzle(format.order).components;
638 const BVec4 chnMask = BVec4(deInRange32(map[0], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
639 deInRange32(map[1], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
640 deInRange32(map[2], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
641 deInRange32(map[3], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE);
642 const IVec4 chnSwz = IVec4((chnMask[0]) ? ((int)map[0]) : (0),
643 (chnMask[1]) ? ((int)map[1]) : (0),
644 (chnMask[2]) ? ((int)map[2]) : (0),
645 (chnMask[3]) ? ((int)map[3]) : (0));
647 return select(chnBits.swizzle(chnSwz.x(), chnSwz.y(), chnSwz.z(), chnSwz.w()), IVec4(0), chnMask);
650 BVec4 getTextureFormatChannelMask (const TextureFormat& format)
652 const TextureSwizzle::Channel* const map = getChannelReadSwizzle(format.order).components;
653 return BVec4(deInRange32(map[0], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
654 deInRange32(map[1], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
655 deInRange32(map[2], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE,
656 deInRange32(map[3], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE);
659 static inline float linearInterpolate (float t, float minVal, float maxVal)
661 return minVal + (maxVal - minVal) * t;
664 static inline Vec4 linearInterpolate (float t, const Vec4& a, const Vec4& b)
666 return a + (b - a) * t;
671 CLEAR_OPTIMIZE_THRESHOLD = 128,
672 CLEAR_OPTIMIZE_MAX_PIXEL_SIZE = 8
675 inline void fillRow (const PixelBufferAccess& dst, int y, int z, int pixelSize, const deUint8* pixel)
677 DE_ASSERT(dst.getPixelPitch() == pixelSize); // only tightly packed
679 deUint8* dstPtr = (deUint8*)dst.getPixelPtr(0, y, z);
680 int width = dst.getWidth();
682 if (pixelSize == 8 && deIsAlignedPtr(dstPtr, pixelSize))
685 memcpy(&val, pixel, sizeof(val));
687 for (int i = 0; i < width; i++)
688 ((deUint64*)dstPtr)[i] = val;
690 else if (pixelSize == 4 && deIsAlignedPtr(dstPtr, pixelSize))
693 memcpy(&val, pixel, sizeof(val));
695 for (int i = 0; i < width; i++)
696 ((deUint32*)dstPtr)[i] = val;
700 for (int i = 0; i < width; i++)
701 for (int j = 0; j < pixelSize; j++)
702 dstPtr[i*pixelSize+j] = pixel[j];
706 void clear (const PixelBufferAccess& access, const Vec4& color)
708 const int pixelSize = access.getFormat().getPixelSize();
709 const int pixelPitch = access.getPixelPitch();
710 const bool rowPixelsTightlyPacked = (pixelSize == pixelPitch);
712 if (access.getWidth()*access.getHeight()*access.getDepth() >= CLEAR_OPTIMIZE_THRESHOLD &&
713 pixelSize < CLEAR_OPTIMIZE_MAX_PIXEL_SIZE && rowPixelsTightlyPacked)
715 // Convert to destination format.
718 deUint8 u8[CLEAR_OPTIMIZE_MAX_PIXEL_SIZE];
719 deUint64 u64; // Forces 64-bit alignment.
721 DE_STATIC_ASSERT(sizeof(pixel) == CLEAR_OPTIMIZE_MAX_PIXEL_SIZE);
722 PixelBufferAccess(access.getFormat(), 1, 1, 1, 0, 0, &pixel.u8[0]).setPixel(color, 0, 0);
724 for (int z = 0; z < access.getDepth(); z++)
725 for (int y = 0; y < access.getHeight(); y++)
726 fillRow(access, y, z, pixelSize, &pixel.u8[0]);
730 for (int z = 0; z < access.getDepth(); z++)
731 for (int y = 0; y < access.getHeight(); y++)
732 for (int x = 0; x < access.getWidth(); x++)
733 access.setPixel(color, x, y, z);
737 void clear (const PixelBufferAccess& access, const IVec4& color)
739 const int pixelSize = access.getFormat().getPixelSize();
740 const int pixelPitch = access.getPixelPitch();
741 const bool rowPixelsTightlyPacked = (pixelSize == pixelPitch);
743 if (access.getWidth()*access.getHeight()*access.getDepth() >= CLEAR_OPTIMIZE_THRESHOLD &&
744 pixelSize < CLEAR_OPTIMIZE_MAX_PIXEL_SIZE && rowPixelsTightlyPacked)
746 // Convert to destination format.
749 deUint8 u8[CLEAR_OPTIMIZE_MAX_PIXEL_SIZE];
750 deUint64 u64; // Forces 64-bit alignment.
752 DE_STATIC_ASSERT(sizeof(pixel) == CLEAR_OPTIMIZE_MAX_PIXEL_SIZE);
753 PixelBufferAccess(access.getFormat(), 1, 1, 1, 0, 0, &pixel.u8[0]).setPixel(color, 0, 0);
755 for (int z = 0; z < access.getDepth(); z++)
756 for (int y = 0; y < access.getHeight(); y++)
757 fillRow(access, y, z, pixelSize, &pixel.u8[0]);
761 for (int z = 0; z < access.getDepth(); z++)
762 for (int y = 0; y < access.getHeight(); y++)
763 for (int x = 0; x < access.getWidth(); x++)
764 access.setPixel(color, x, y, z);
768 void clear (const PixelBufferAccess& access, const UVec4& color)
770 clear(access, color.cast<deInt32>());
773 void clearDepth (const PixelBufferAccess& access, float depth)
775 DE_ASSERT(access.getFormat().order == TextureFormat::DS || access.getFormat().order == TextureFormat::D);
777 clear(getEffectiveDepthStencilAccess(access, Sampler::MODE_DEPTH), tcu::Vec4(depth, 0.0f, 0.0f, 0.0f));
780 void clearStencil (const PixelBufferAccess& access, int stencil)
782 DE_ASSERT(access.getFormat().order == TextureFormat::DS || access.getFormat().order == TextureFormat::S);
784 clear(getEffectiveDepthStencilAccess(access, Sampler::MODE_STENCIL), tcu::UVec4(stencil, 0u, 0u, 0u));
787 static void fillWithComponentGradients1D (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal)
789 DE_ASSERT(access.getHeight() == 1);
790 for (int x = 0; x < access.getWidth(); x++)
792 float s = ((float)x + 0.5f) / (float)access.getWidth();
794 float r = linearInterpolate(s, minVal.x(), maxVal.x());
795 float g = linearInterpolate(s, minVal.y(), maxVal.y());
796 float b = linearInterpolate(s, minVal.z(), maxVal.z());
797 float a = linearInterpolate(s, minVal.w(), maxVal.w());
799 access.setPixel(tcu::Vec4(r, g, b, a), x, 0);
803 static void fillWithComponentGradients2D (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal)
805 for (int y = 0; y < access.getHeight(); y++)
807 for (int x = 0; x < access.getWidth(); x++)
809 float s = ((float)x + 0.5f) / (float)access.getWidth();
810 float t = ((float)y + 0.5f) / (float)access.getHeight();
812 float r = linearInterpolate(( s + t) *0.5f, minVal.x(), maxVal.x());
813 float g = linearInterpolate(( s + (1.0f-t))*0.5f, minVal.y(), maxVal.y());
814 float b = linearInterpolate(((1.0f-s) + t) *0.5f, minVal.z(), maxVal.z());
815 float a = linearInterpolate(((1.0f-s) + (1.0f-t))*0.5f, minVal.w(), maxVal.w());
817 access.setPixel(tcu::Vec4(r, g, b, a), x, y);
822 static void fillWithComponentGradients3D (const PixelBufferAccess& dst, const Vec4& minVal, const Vec4& maxVal)
824 for (int z = 0; z < dst.getDepth(); z++)
826 for (int y = 0; y < dst.getHeight(); y++)
828 for (int x = 0; x < dst.getWidth(); x++)
830 float s = ((float)x + 0.5f) / (float)dst.getWidth();
831 float t = ((float)y + 0.5f) / (float)dst.getHeight();
832 float p = ((float)z + 0.5f) / (float)dst.getDepth();
834 float r = linearInterpolate(s, minVal.x(), maxVal.x());
835 float g = linearInterpolate(t, minVal.y(), maxVal.y());
836 float b = linearInterpolate(p, minVal.z(), maxVal.z());
837 float a = linearInterpolate(1.0f - (s+t+p)/3.0f, minVal.w(), maxVal.w());
839 dst.setPixel(tcu::Vec4(r, g, b, a), x, y, z);
845 void fillWithComponentGradients (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal)
847 if (isCombinedDepthStencilType(access.getFormat().type))
849 const bool hasDepth = access.getFormat().order == tcu::TextureFormat::DS || access.getFormat().order == tcu::TextureFormat::D;
850 const bool hasStencil = access.getFormat().order == tcu::TextureFormat::DS || access.getFormat().order == tcu::TextureFormat::S;
852 DE_ASSERT(hasDepth || hasStencil);
854 // For combined formats, treat D and S as separate channels
856 fillWithComponentGradients(getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_DEPTH), minVal, maxVal);
858 fillWithComponentGradients(getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_STENCIL), minVal.swizzle(3,2,1,0), maxVal.swizzle(3,2,1,0));
862 if (access.getHeight() == 1 && access.getDepth() == 1)
863 fillWithComponentGradients1D(access, minVal, maxVal);
864 else if (access.getDepth() == 1)
865 fillWithComponentGradients2D(access, minVal, maxVal);
867 fillWithComponentGradients3D(access, minVal, maxVal);
871 static void fillWithGrid1D (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB)
873 for (int x = 0; x < access.getWidth(); x++)
875 int mx = (x / cellSize) % 2;
878 access.setPixel(colorB, x, 0);
880 access.setPixel(colorA, x, 0);
884 static void fillWithGrid2D (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB)
886 for (int y = 0; y < access.getHeight(); y++)
888 for (int x = 0; x < access.getWidth(); x++)
890 int mx = (x / cellSize) % 2;
891 int my = (y / cellSize) % 2;
894 access.setPixel(colorB, x, y);
896 access.setPixel(colorA, x, y);
901 static void fillWithGrid3D (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB)
903 for (int z = 0; z < access.getDepth(); z++)
905 for (int y = 0; y < access.getHeight(); y++)
907 for (int x = 0; x < access.getWidth(); x++)
909 int mx = (x / cellSize) % 2;
910 int my = (y / cellSize) % 2;
911 int mz = (z / cellSize) % 2;
914 access.setPixel(colorB, x, y, z);
916 access.setPixel(colorA, x, y, z);
922 void fillWithGrid (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB)
924 if (isCombinedDepthStencilType(access.getFormat().type))
926 const bool hasDepth = access.getFormat().order == tcu::TextureFormat::DS || access.getFormat().order == tcu::TextureFormat::D;
927 const bool hasStencil = access.getFormat().order == tcu::TextureFormat::DS || access.getFormat().order == tcu::TextureFormat::S;
929 DE_ASSERT(hasDepth || hasStencil);
931 // For combined formats, treat D and S as separate channels
933 fillWithGrid(getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_DEPTH), cellSize, colorA, colorB);
935 fillWithGrid(getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_STENCIL), cellSize, colorA.swizzle(3,2,1,0), colorB.swizzle(3,2,1,0));
939 if (access.getHeight() == 1 && access.getDepth() == 1)
940 fillWithGrid1D(access, cellSize, colorA, colorB);
941 else if (access.getDepth() == 1)
942 fillWithGrid2D(access, cellSize, colorA, colorB);
944 fillWithGrid3D(access, cellSize, colorA, colorB);
948 void fillWithRepeatableGradient (const PixelBufferAccess& access, const Vec4& colorA, const Vec4& colorB)
950 for (int y = 0; y < access.getHeight(); y++)
952 for (int x = 0; x < access.getWidth(); x++)
954 float s = ((float)x + 0.5f) / (float)access.getWidth();
955 float t = ((float)y + 0.5f) / (float)access.getHeight();
957 float a = s > 0.5f ? (2.0f - 2.0f*s) : 2.0f*s;
958 float b = t > 0.5f ? (2.0f - 2.0f*t) : 2.0f*t;
960 float p = deFloatClamp(deFloatSqrt(a*a + b*b), 0.0f, 1.0f);
961 access.setPixel(linearInterpolate(p, colorA, colorB), x, y);
966 void fillWithRGBAQuads (const PixelBufferAccess& dst)
968 TCU_CHECK_INTERNAL(dst.getDepth() == 1);
969 int width = dst.getWidth();
970 int height = dst.getHeight();
974 clear(getSubregion(dst, 0, 0, 0, left, top, 1), Vec4(1.0f, 0.0f, 0.0f, 1.0f));
975 clear(getSubregion(dst, left, 0, 0, width-left, top, 1), Vec4(0.0f, 1.0f, 0.0f, 1.0f));
976 clear(getSubregion(dst, 0, top, 0, left, height-top, 1), Vec4(0.0f, 0.0f, 1.0f, 0.0f));
977 clear(getSubregion(dst, left, top, 0, width-left, height-top, 1), Vec4(0.5f, 0.5f, 0.5f, 1.0f));
980 // \todo [2012-11-13 pyry] There is much better metaballs code in CL SIR value generators.
981 void fillWithMetaballs (const PixelBufferAccess& dst, int numBalls, deUint32 seed)
983 TCU_CHECK_INTERNAL(dst.getDepth() == 1);
984 std::vector<Vec2> points(numBalls);
985 de::Random rnd(seed);
987 for (int i = 0; i < numBalls; i++)
989 float x = rnd.getFloat();
990 float y = rnd.getFloat();
991 points[i] = (Vec2(x, y));
994 for (int y = 0; y < dst.getHeight(); y++)
995 for (int x = 0; x < dst.getWidth(); x++)
997 Vec2 p((float)x/(float)dst.getWidth(), (float)y/(float)dst.getHeight());
1000 for (std::vector<Vec2>::const_iterator i = points.begin(); i != points.end(); i++)
1003 float f = 0.01f / (d.x()*d.x() + d.y()*d.y());
1008 dst.setPixel(Vec4(sum), x, y);
1012 void copy (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src)
1014 DE_ASSERT(src.getSize() == dst.getSize());
1016 const int width = dst.getWidth();
1017 const int height = dst.getHeight();
1018 const int depth = dst.getDepth();
1020 const int srcPixelSize = src.getFormat().getPixelSize();
1021 const int dstPixelSize = dst.getFormat().getPixelSize();
1022 const int srcPixelPitch = src.getPixelPitch();
1023 const int dstPixelPitch = dst.getPixelPitch();
1024 const bool srcTightlyPacked = (srcPixelSize == srcPixelPitch);
1025 const bool dstTightlyPacked = (dstPixelSize == dstPixelPitch);
1027 const bool srcHasDepth = (src.getFormat().order == tcu::TextureFormat::DS || src.getFormat().order == tcu::TextureFormat::D);
1028 const bool srcHasStencil = (src.getFormat().order == tcu::TextureFormat::DS || src.getFormat().order == tcu::TextureFormat::S);
1029 const bool dstHasDepth = (dst.getFormat().order == tcu::TextureFormat::DS || dst.getFormat().order == tcu::TextureFormat::D);
1030 const bool dstHasStencil = (dst.getFormat().order == tcu::TextureFormat::DS || dst.getFormat().order == tcu::TextureFormat::S);
1032 if (src.getFormat() == dst.getFormat() && srcTightlyPacked && dstTightlyPacked)
1034 // Fast-path for matching formats.
1035 for (int z = 0; z < depth; z++)
1036 for (int y = 0; y < height; y++)
1037 deMemcpy(dst.getPixelPtr(0, y, z), src.getPixelPtr(0, y, z), srcPixelSize*width);
1039 else if (src.getFormat() == dst.getFormat())
1041 // Bit-exact copy for matching formats.
1042 for (int z = 0; z < depth; z++)
1043 for (int y = 0; y < height; y++)
1044 for (int x = 0; x < width; x++)
1045 deMemcpy(dst.getPixelPtr(x, y, z), src.getPixelPtr(x, y, z), srcPixelSize);
1047 else if (srcHasDepth || srcHasStencil || dstHasDepth || dstHasStencil)
1049 DE_ASSERT((srcHasDepth && dstHasDepth) || (srcHasStencil && dstHasStencil)); // must have at least one common channel
1051 if (dstHasDepth && srcHasDepth)
1053 for (int z = 0; z < depth; z++)
1054 for (int y = 0; y < height; y++)
1055 for (int x = 0; x < width; x++)
1056 dst.setPixDepth(src.getPixDepth(x, y, z), x, y, z);
1058 else if (dstHasDepth && !srcHasDepth)
1060 // consistency with color copies
1061 tcu::clearDepth(dst, 0.0f);
1064 if (dstHasStencil && srcHasStencil)
1066 for (int z = 0; z < depth; z++)
1067 for (int y = 0; y < height; y++)
1068 for (int x = 0; x < width; x++)
1069 dst.setPixStencil(src.getPixStencil(x, y, z), x, y, z);
1071 else if (dstHasStencil && !srcHasStencil)
1073 // consistency with color copies
1074 tcu::clearStencil(dst, 0u);
1079 TextureChannelClass srcClass = getTextureChannelClass(src.getFormat().type);
1080 TextureChannelClass dstClass = getTextureChannelClass(dst.getFormat().type);
1081 bool srcIsInt = srcClass == TEXTURECHANNELCLASS_SIGNED_INTEGER || srcClass == TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
1082 bool dstIsInt = dstClass == TEXTURECHANNELCLASS_SIGNED_INTEGER || dstClass == TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
1084 if (srcIsInt && dstIsInt)
1086 for (int z = 0; z < depth; z++)
1087 for (int y = 0; y < height; y++)
1088 for (int x = 0; x < width; x++)
1089 dst.setPixel(src.getPixelInt(x, y, z), x, y, z);
1093 for (int z = 0; z < depth; z++)
1094 for (int y = 0; y < height; y++)
1095 for (int x = 0; x < width; x++)
1096 dst.setPixel(src.getPixel(x, y, z), x, y, z);
1101 void scale (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src, Sampler::FilterMode filter)
1103 DE_ASSERT(filter == Sampler::NEAREST || filter == Sampler::LINEAR);
1105 Sampler sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE,
1106 filter, filter, 0.0f, false);
1108 float sX = (float)src.getWidth() / (float)dst.getWidth();
1109 float sY = (float)src.getHeight() / (float)dst.getHeight();
1110 float sZ = (float)src.getDepth() / (float)dst.getDepth();
1112 if (dst.getDepth() == 1 && src.getDepth() == 1)
1114 for (int y = 0; y < dst.getHeight(); y++)
1115 for (int x = 0; x < dst.getWidth(); x++)
1116 dst.setPixel(linearToSRGBIfNeeded(dst.getFormat(), src.sample2D(sampler, filter, ((float)x+0.5f)*sX, ((float)y+0.5f)*sY, 0)), x, y);
1120 for (int z = 0; z < dst.getDepth(); z++)
1121 for (int y = 0; y < dst.getHeight(); y++)
1122 for (int x = 0; x < dst.getWidth(); x++)
1123 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);
1127 void estimatePixelValueRange (const ConstPixelBufferAccess& access, Vec4& minVal, Vec4& maxVal)
1129 const TextureFormat& format = access.getFormat();
1131 switch (getTextureChannelClass(format.type))
1133 case TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1134 // Normalized unsigned formats.
1135 minVal = Vec4(0.0f);
1136 maxVal = Vec4(1.0f);
1139 case TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1140 // Normalized signed formats.
1141 minVal = Vec4(-1.0f);
1142 maxVal = Vec4(+1.0f);
1146 // \note Samples every 4/8th pixel.
1147 minVal = Vec4(std::numeric_limits<float>::max());
1148 maxVal = Vec4(std::numeric_limits<float>::min());
1150 for (int z = 0; z < access.getDepth(); z += 2)
1152 for (int y = 0; y < access.getHeight(); y += 2)
1154 for (int x = 0; x < access.getWidth(); x += 2)
1156 Vec4 p = access.getPixel(x, y, z);
1158 minVal[0] = (deFloatIsNaN(p[0]) ? minVal[0] : de::min(minVal[0], p[0]));
1159 minVal[1] = (deFloatIsNaN(p[1]) ? minVal[1] : de::min(minVal[1], p[1]));
1160 minVal[2] = (deFloatIsNaN(p[2]) ? minVal[2] : de::min(minVal[2], p[2]));
1161 minVal[3] = (deFloatIsNaN(p[3]) ? minVal[3] : de::min(minVal[3], p[3]));
1163 maxVal[0] = (deFloatIsNaN(p[0]) ? maxVal[0] : de::max(maxVal[0], p[0]));
1164 maxVal[1] = (deFloatIsNaN(p[1]) ? maxVal[1] : de::max(maxVal[1], p[1]));
1165 maxVal[2] = (deFloatIsNaN(p[2]) ? maxVal[2] : de::max(maxVal[2], p[2]));
1166 maxVal[3] = (deFloatIsNaN(p[3]) ? maxVal[3] : de::max(maxVal[3], p[3]));
1174 void computePixelScaleBias (const ConstPixelBufferAccess& access, Vec4& scale, Vec4& bias)
1176 Vec4 minVal, maxVal;
1177 estimatePixelValueRange(access, minVal, maxVal);
1179 const float eps = 0.0001f;
1181 for (int c = 0; c < 4; c++)
1183 if (maxVal[c] - minVal[c] < eps)
1185 scale[c] = (maxVal[c] < eps) ? 1.0f : (1.0f / maxVal[c]);
1186 bias[c] = (c == 3) ? (1.0f - maxVal[c]*scale[c]) : (0.0f - minVal[c]*scale[c]);
1190 scale[c] = 1.0f / (maxVal[c] - minVal[c]);
1191 bias[c] = 0.0f - minVal[c]*scale[c];
1196 int getCubeArrayFaceIndex (CubeFace face)
1198 DE_ASSERT((int)face >= 0 && face < CUBEFACE_LAST);
1202 case CUBEFACE_POSITIVE_X: return 0;
1203 case CUBEFACE_NEGATIVE_X: return 1;
1204 case CUBEFACE_POSITIVE_Y: return 2;
1205 case CUBEFACE_NEGATIVE_Y: return 3;
1206 case CUBEFACE_POSITIVE_Z: return 4;
1207 case CUBEFACE_NEGATIVE_Z: return 5;
1214 deUint32 packRGB999E5 (const tcu::Vec4& color)
1216 const int mBits = 9;
1217 const int eBits = 5;
1218 const int eBias = 15;
1219 const int eMax = (1<<eBits)-1;
1220 const float maxVal = (float)(((1<<mBits) - 1) * (1<<(eMax-eBias))) / (float)(1<<mBits);
1222 float rc = deFloatClamp(color[0], 0.0f, maxVal);
1223 float gc = deFloatClamp(color[1], 0.0f, maxVal);
1224 float bc = deFloatClamp(color[2], 0.0f, maxVal);
1225 float maxc = de::max(rc, de::max(gc, bc));
1226 int expp = de::max(-eBias - 1, deFloorFloatToInt32(deFloatLog2(maxc))) + 1 + eBias;
1227 float e = deFloatPow(2.0f, (float)(expp-eBias-mBits));
1228 int maxs = deFloorFloatToInt32(maxc / e + 0.5f);
1230 deUint32 exps = maxs == (1<<mBits) ? expp+1 : expp;
1231 deUint32 rs = (deUint32)deClamp32(deFloorFloatToInt32(rc / e + 0.5f), 0, (1<<9)-1);
1232 deUint32 gs = (deUint32)deClamp32(deFloorFloatToInt32(gc / e + 0.5f), 0, (1<<9)-1);
1233 deUint32 bs = (deUint32)deClamp32(deFloorFloatToInt32(bc / e + 0.5f), 0, (1<<9)-1);
1235 DE_ASSERT((exps & ~((1<<5)-1)) == 0);
1236 DE_ASSERT((rs & ~((1<<9)-1)) == 0);
1237 DE_ASSERT((gs & ~((1<<9)-1)) == 0);
1238 DE_ASSERT((bs & ~((1<<9)-1)) == 0);
1240 return rs | (gs << 9) | (bs << 18) | (exps << 27);
1245 static const void* addOffset (const void* ptr, int numBytes)
1247 return (const deUint8*)ptr + numBytes;
1250 static void* addOffset (void* ptr, int numBytes)
1252 return (deUint8*)ptr + numBytes;
1255 template <typename AccessType>
1256 static AccessType toSamplerAccess (const AccessType& baseAccess, Sampler::DepthStencilMode mode)
1258 // make sure to update this if type table is updated
1259 DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 38);
1261 if (!isCombinedDepthStencilType(baseAccess.getFormat().type))
1265 #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
1266 const deUint32 uint32ByteOffsetBits0To8 = 0; //!< least significant byte in the lowest address
1267 const deUint32 uint32ByteOffsetBits0To24 = 0;
1268 const deUint32 uint32ByteOffsetBits8To32 = 1;
1269 const deUint32 uint32ByteOffsetBits16To32 = 2;
1270 const deUint32 uint32ByteOffsetBits24To32 = 3;
1272 const deUint32 uint32ByteOffsetBits0To8 = 3; //!< least significant byte in the highest address
1273 const deUint32 uint32ByteOffsetBits0To24 = 1;
1274 const deUint32 uint32ByteOffsetBits8To32 = 0;
1275 const deUint32 uint32ByteOffsetBits16To32 = 0;
1276 const deUint32 uint32ByteOffsetBits24To32 = 0;
1279 // Sampled channel must exist
1280 DE_ASSERT(baseAccess.getFormat().order == TextureFormat::DS ||
1281 (mode == Sampler::MODE_DEPTH && baseAccess.getFormat().order == TextureFormat::D) ||
1282 (mode == Sampler::MODE_STENCIL && baseAccess.getFormat().order == TextureFormat::S));
1284 // combined formats have multiple channel classes, detect on sampler settings
1285 switch (baseAccess.getFormat().type)
1287 case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
1289 if (mode == Sampler::MODE_DEPTH)
1291 // select the float component
1292 return AccessType(TextureFormat(TextureFormat::D, TextureFormat::FLOAT),
1293 baseAccess.getSize(),
1294 baseAccess.getPitch(),
1295 baseAccess.getDataPtr());
1297 else if (mode == Sampler::MODE_STENCIL)
1299 // select the uint 8 component
1300 return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8),
1301 baseAccess.getSize(),
1302 baseAccess.getPitch(),
1303 addOffset(baseAccess.getDataPtr(), 4 + uint32ByteOffsetBits0To8));
1307 // unknown sampler mode
1309 return AccessType();
1313 case TextureFormat::UNSIGNED_INT_16_8_8:
1315 if (mode == Sampler::MODE_DEPTH)
1317 // select the unorm16 component
1318 return AccessType(TextureFormat(TextureFormat::D, TextureFormat::UNORM_INT16),
1319 baseAccess.getSize(),
1320 baseAccess.getPitch(),
1321 addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits16To32));
1323 else if (mode == Sampler::MODE_STENCIL)
1325 // select the uint 8 component
1326 return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8),
1327 baseAccess.getSize(),
1328 baseAccess.getPitch(),
1329 addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits0To8));
1333 // unknown sampler mode
1335 return AccessType();
1339 case TextureFormat::UNSIGNED_INT_24_8:
1341 if (mode == Sampler::MODE_DEPTH)
1343 // select the unorm24 component
1344 return AccessType(TextureFormat(TextureFormat::D, TextureFormat::UNORM_INT24),
1345 baseAccess.getSize(),
1346 baseAccess.getPitch(),
1347 addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits8To32));
1349 else if (mode == Sampler::MODE_STENCIL)
1351 // select the uint 8 component
1352 return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8),
1353 baseAccess.getSize(),
1354 baseAccess.getPitch(),
1355 addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits0To8));
1359 // unknown sampler mode
1361 return AccessType();
1365 case TextureFormat::UNSIGNED_INT_24_8_REV:
1367 if (mode == Sampler::MODE_DEPTH)
1369 // select the unorm24 component
1370 return AccessType(TextureFormat(TextureFormat::D, TextureFormat::UNORM_INT24),
1371 baseAccess.getSize(),
1372 baseAccess.getPitch(),
1373 addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits0To24));
1375 else if (mode == Sampler::MODE_STENCIL)
1377 // select the uint 8 component
1378 return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8),
1379 baseAccess.getSize(),
1380 baseAccess.getPitch(),
1381 addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits24To32));
1385 // unknown sampler mode
1387 return AccessType();
1393 // unknown combined format
1395 return AccessType();
1401 PixelBufferAccess getEffectiveDepthStencilAccess (const PixelBufferAccess& baseAccess, Sampler::DepthStencilMode mode)
1403 return toSamplerAccess<PixelBufferAccess>(baseAccess, mode);
1406 ConstPixelBufferAccess getEffectiveDepthStencilAccess (const ConstPixelBufferAccess& baseAccess, Sampler::DepthStencilMode mode)
1408 return toSamplerAccess<ConstPixelBufferAccess>(baseAccess, mode);
1411 TextureFormat getEffectiveDepthStencilTextureFormat (const TextureFormat& baseFormat, Sampler::DepthStencilMode mode)
1413 return toSamplerAccess(ConstPixelBufferAccess(baseFormat, IVec3(0, 0, 0), DE_NULL), mode).getFormat();
1416 template <typename ViewType>
1417 ViewType getEffectiveTView (const ViewType& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
1419 storage.resize(src.getNumLevels());
1421 ViewType view = ViewType(src.getNumLevels(), &storage[0]);
1423 for (int levelNdx = 0; levelNdx < src.getNumLevels(); ++levelNdx)
1424 storage[levelNdx] = tcu::getEffectiveDepthStencilAccess(src.getLevel(levelNdx), sampler.depthStencilMode);
1429 tcu::TextureCubeView getEffectiveTView (const tcu::TextureCubeView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
1431 storage.resize(tcu::CUBEFACE_LAST * src.getNumLevels());
1433 const tcu::ConstPixelBufferAccess* storagePtrs[tcu::CUBEFACE_LAST] =
1435 &storage[0 * src.getNumLevels()],
1436 &storage[1 * src.getNumLevels()],
1437 &storage[2 * src.getNumLevels()],
1438 &storage[3 * src.getNumLevels()],
1439 &storage[4 * src.getNumLevels()],
1440 &storage[5 * src.getNumLevels()],
1443 tcu::TextureCubeView view = tcu::TextureCubeView(src.getNumLevels(), storagePtrs);
1445 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx)
1446 for (int levelNdx = 0; levelNdx < src.getNumLevels(); ++levelNdx)
1447 storage[faceNdx * src.getNumLevels() + levelNdx] = tcu::getEffectiveDepthStencilAccess(src.getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), sampler.depthStencilMode);
1452 tcu::Texture1DView getEffectiveTextureView (const tcu::Texture1DView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
1454 return getEffectiveTView(src, storage, sampler);
1457 tcu::Texture2DView getEffectiveTextureView (const tcu::Texture2DView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
1459 return getEffectiveTView(src, storage, sampler);
1462 tcu::Texture3DView getEffectiveTextureView (const tcu::Texture3DView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
1464 return getEffectiveTView(src, storage, sampler);
1467 tcu::Texture1DArrayView getEffectiveTextureView (const tcu::Texture1DArrayView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
1469 return getEffectiveTView(src, storage, sampler);
1472 tcu::Texture2DArrayView getEffectiveTextureView (const tcu::Texture2DArrayView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
1474 return getEffectiveTView(src, storage, sampler);
1477 tcu::TextureCubeView getEffectiveTextureView (const tcu::TextureCubeView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
1479 return getEffectiveTView(src, storage, sampler);
1482 tcu::TextureCubeArrayView getEffectiveTextureView (const tcu::TextureCubeArrayView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler)
1484 return getEffectiveTView(src, storage, sampler);
1487 //! Returns the effective swizzle of a border color. The effective swizzle is the
1488 //! equal to first writing an RGBA color with a write swizzle and then reading
1489 //! it back using a read swizzle, i.e. BorderSwizzle(c) == readSwizzle(writeSwizzle(C))
1490 static const TextureSwizzle& getBorderColorReadSwizzle (TextureFormat::ChannelOrder order)
1492 // make sure to update these tables when channel orders are updated
1493 DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 21);
1495 static const TextureSwizzle INV = {{ TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ONE }};
1496 static const TextureSwizzle R = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ONE }};
1497 static const TextureSwizzle A = {{ TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_3 }};
1498 static const TextureSwizzle I = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0 }};
1499 static const TextureSwizzle L = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_ONE }};
1500 static const TextureSwizzle LA = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3 }};
1501 static const TextureSwizzle RG = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ONE }};
1502 static const TextureSwizzle RA = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_3 }};
1503 static const TextureSwizzle RGB = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_2, TextureSwizzle::CHANNEL_ONE }};
1504 static const TextureSwizzle RGBA = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_2, TextureSwizzle::CHANNEL_3 }};
1505 static const TextureSwizzle D = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ONE }};
1506 static const TextureSwizzle S = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ONE }};
1508 const TextureSwizzle* swizzle;
1512 case TextureFormat::R: swizzle = &R; break;
1513 case TextureFormat::A: swizzle = &A; break;
1514 case TextureFormat::I: swizzle = &I; break;
1515 case TextureFormat::L: swizzle = &L; break;
1516 case TextureFormat::LA: swizzle = &LA; break;
1517 case TextureFormat::RG: swizzle = &RG; break;
1518 case TextureFormat::RA: swizzle = &RA; break;
1519 case TextureFormat::RGB: swizzle = &RGB; break;
1520 case TextureFormat::RGBA: swizzle = &RGBA; break;
1521 case TextureFormat::ARGB: swizzle = &RGBA; break;
1522 case TextureFormat::BGR: swizzle = &RGB; break;
1523 case TextureFormat::BGRA: swizzle = &RGBA; break;
1524 case TextureFormat::sR: swizzle = &R; break;
1525 case TextureFormat::sRG: swizzle = &RG; break;
1526 case TextureFormat::sRGB: swizzle = &RGB; break;
1527 case TextureFormat::sRGBA: swizzle = &RGBA; break;
1528 case TextureFormat::sBGR: swizzle = &RGB; break;
1529 case TextureFormat::sBGRA: swizzle = &RGBA; break;
1530 case TextureFormat::D: swizzle = &D; break;
1531 case TextureFormat::S: swizzle = &S; break;
1533 case TextureFormat::DS:
1534 DE_ASSERT(false); // combined depth-stencil border color?
1547 // check that BorderSwizzle(c) == readSwizzle(writeSwizzle(C))
1548 const TextureSwizzle& readSwizzle = getChannelReadSwizzle(order);
1549 const TextureSwizzle& writeSwizzle = getChannelWriteSwizzle(order);
1551 for (int ndx = 0; ndx < 4; ++ndx)
1553 TextureSwizzle::Channel writeRead = readSwizzle.components[ndx];
1554 if (deInRange32(writeRead, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE)
1555 writeRead = writeSwizzle.components[(int)writeRead];
1556 DE_ASSERT(writeRead == swizzle->components[ndx]);
1565 static tcu::UVec4 getNBitUnsignedIntegerVec4MaxValue (const tcu::IVec4& numBits)
1567 return tcu::UVec4((numBits[0] > 0) ? (deUintMaxValue32(numBits[0])) : (0),
1568 (numBits[1] > 0) ? (deUintMaxValue32(numBits[1])) : (0),
1569 (numBits[2] > 0) ? (deUintMaxValue32(numBits[2])) : (0),
1570 (numBits[3] > 0) ? (deUintMaxValue32(numBits[3])) : (0));
1573 static tcu::IVec4 getNBitSignedIntegerVec4MaxValue (const tcu::IVec4& numBits)
1575 return tcu::IVec4((numBits[0] > 0) ? (deIntMaxValue32(numBits[0])) : (0),
1576 (numBits[1] > 0) ? (deIntMaxValue32(numBits[1])) : (0),
1577 (numBits[2] > 0) ? (deIntMaxValue32(numBits[2])) : (0),
1578 (numBits[3] > 0) ? (deIntMaxValue32(numBits[3])) : (0));
1581 static tcu::IVec4 getNBitSignedIntegerVec4MinValue (const tcu::IVec4& numBits)
1583 return tcu::IVec4((numBits[0] > 0) ? (deIntMinValue32(numBits[0])) : (0),
1584 (numBits[1] > 0) ? (deIntMinValue32(numBits[1])) : (0),
1585 (numBits[2] > 0) ? (deIntMinValue32(numBits[2])) : (0),
1586 (numBits[3] > 0) ? (deIntMinValue32(numBits[3])) : (0));
1589 static tcu::Vec4 getTextureBorderColorFloat (const TextureFormat& format, const Sampler& sampler)
1591 const tcu::TextureChannelClass channelClass = getTextureChannelClass(format.type);
1592 const TextureSwizzle::Channel* channelMap = getBorderColorReadSwizzle(format.order).components;
1593 const bool isFloat = channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT;
1594 const bool isSigned = channelClass != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
1595 const float valueMin = (isSigned) ? (-1.0f) : (0.0f);
1596 const float valueMax = 1.0f;
1599 DE_ASSERT(channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT ||
1600 channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ||
1601 channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT);
1603 for (int c = 0; c < 4; c++)
1605 const TextureSwizzle::Channel map = channelMap[c];
1606 if (map == TextureSwizzle::CHANNEL_ZERO)
1608 else if (map == TextureSwizzle::CHANNEL_ONE)
1612 // floating point values are not clamped
1613 result[c] = sampler.borderColor.getAccess<float>()[(int)map];
1617 // fixed point values are clamped to a representable range
1618 result[c] = de::clamp(sampler.borderColor.getAccess<float>()[(int)map], valueMin, valueMax);
1625 static tcu::IVec4 getTextureBorderColorInt (const TextureFormat& format, const Sampler& sampler)
1627 const tcu::TextureChannelClass channelClass = getTextureChannelClass(format.type);
1628 const TextureSwizzle::Channel* channelMap = getBorderColorReadSwizzle(format.order).components;
1629 const IVec4 channelBits = getChannelBitDepth(format.type);
1630 const IVec4 valueMin = getNBitSignedIntegerVec4MinValue(channelBits);
1631 const IVec4 valueMax = getNBitSignedIntegerVec4MaxValue(channelBits);
1634 DE_ASSERT(channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
1635 DE_UNREF(channelClass);
1637 for (int c = 0; c < 4; c++)
1639 const TextureSwizzle::Channel map = channelMap[c];
1640 if (map == TextureSwizzle::CHANNEL_ZERO)
1642 else if (map == TextureSwizzle::CHANNEL_ONE)
1646 // integer values are clamped to a representable range
1647 result[c] = de::clamp(sampler.borderColor.getAccess<deInt32>()[(int)map], valueMin[(int)map], valueMax[(int)map]);
1654 static tcu::UVec4 getTextureBorderColorUint (const TextureFormat& format, const Sampler& sampler)
1656 const tcu::TextureChannelClass channelClass = getTextureChannelClass(format.type);
1657 const TextureSwizzle::Channel* channelMap = getBorderColorReadSwizzle(format.order).components;
1658 const IVec4 channelBits = getChannelBitDepth(format.type);
1659 const UVec4 valueMax = getNBitUnsignedIntegerVec4MaxValue(channelBits);
1662 DE_ASSERT(channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
1663 DE_UNREF(channelClass);
1665 for (int c = 0; c < 4; c++)
1667 const TextureSwizzle::Channel map = channelMap[c];
1668 if (map == TextureSwizzle::CHANNEL_ZERO)
1670 else if (map == TextureSwizzle::CHANNEL_ONE)
1674 // integer values are clamped to a representable range
1675 result[c] = de::min(sampler.borderColor.getAccess<deUint32>()[(int)map], valueMax[(int)map]);
1682 template <typename ScalarType>
1683 tcu::Vector<ScalarType, 4> sampleTextureBorder (const TextureFormat& format, const Sampler& sampler)
1685 const tcu::TextureChannelClass channelClass = getTextureChannelClass(format.type);
1687 switch (channelClass)
1689 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1690 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1691 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1692 return getTextureBorderColorFloat(format, sampler).cast<ScalarType>();
1694 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1695 return getTextureBorderColorInt(format, sampler).cast<ScalarType>();
1697 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1698 return getTextureBorderColorUint(format, sampler).cast<ScalarType>();
1702 return tcu::Vector<ScalarType, 4>();
1707 template tcu::Vector<float, 4> sampleTextureBorder (const TextureFormat& format, const Sampler& sampler);
1708 template tcu::Vector<deInt32, 4> sampleTextureBorder (const TextureFormat& format, const Sampler& sampler);
1709 template tcu::Vector<deUint32, 4> sampleTextureBorder (const TextureFormat& format, const Sampler& sampler);