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