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