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