Add support for 10 and 12bit packed unorm formats
[platform/upstream/VK-GL-CTS.git] / framework / common / tcuTextureUtil.cpp
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
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
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 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
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 == 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
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 == 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
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
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
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
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  *//*--------------------------------------------------------------------*/
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  *//*--------------------------------------------------------------------*/
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  *//*--------------------------------------------------------------------*/
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  *//*--------------------------------------------------------------------*/
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  *//*--------------------------------------------------------------------*/
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  *//*--------------------------------------------------------------------*/
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
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  *//*--------------------------------------------------------------------*/
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
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
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
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
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
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
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
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
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
667 static inline float linearInterpolate (float t, float minVal, float maxVal)
668 {
669         return minVal + (maxVal - minVal) * t;
670 }
671
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
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
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
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
776 void clear (const PixelBufferAccess& access, const UVec4& color)
777 {
778         clear(access, color.cast<deInt32>());
779 }
780
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
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
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
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
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
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
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
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
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
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
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
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.
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
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
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
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
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
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
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
1253 static const void* addOffset (const void* ptr, int numBytes)
1254 {
1255         return (const deUint8*)ptr + numBytes;
1256 }
1257
1258 static void* addOffset (void* ptr, int numBytes)
1259 {
1260         return (deUint8*)ptr + numBytes;
1261 }
1262
1263 template <typename AccessType>
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
1409 PixelBufferAccess getEffectiveDepthStencilAccess (const PixelBufferAccess& baseAccess, Sampler::DepthStencilMode mode)
1410 {
1411         return toSamplerAccess<PixelBufferAccess>(baseAccess, mode);
1412 }
1413
1414 ConstPixelBufferAccess getEffectiveDepthStencilAccess (const ConstPixelBufferAccess& baseAccess, Sampler::DepthStencilMode mode)
1415 {
1416         return toSamplerAccess<ConstPixelBufferAccess>(baseAccess, mode);
1417 }
1418
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>
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
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
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
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
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
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
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
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
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))
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
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
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
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
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
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
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>
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