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