Add dual-source blending tests
[platform/upstream/VK-GL-CTS.git] / framework / common / tcuCompressedTexture.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 Compressed Texture Utilities.
22  *//*--------------------------------------------------------------------*/
23
24 #include "tcuCompressedTexture.hpp"
25 #include "tcuTextureUtil.hpp"
26 #include "tcuAstcUtil.hpp"
27
28 #include "deStringUtil.hpp"
29 #include "deFloat16.h"
30
31 #include <algorithm>
32
33 namespace tcu
34 {
35
36 int getBlockSize (CompressedTexFormat format)
37 {
38         if (isAstcFormat(format))
39         {
40                 return astc::BLOCK_SIZE_BYTES;
41         }
42         else if (isEtcFormat(format))
43         {
44                 switch (format)
45                 {
46                         case COMPRESSEDTEXFORMAT_ETC1_RGB8:                                                     return 8;
47                         case COMPRESSEDTEXFORMAT_EAC_R11:                                                       return 8;
48                         case COMPRESSEDTEXFORMAT_EAC_SIGNED_R11:                                        return 8;
49                         case COMPRESSEDTEXFORMAT_EAC_RG11:                                                      return 16;
50                         case COMPRESSEDTEXFORMAT_EAC_SIGNED_RG11:                                       return 16;
51                         case COMPRESSEDTEXFORMAT_ETC2_RGB8:                                                     return 8;
52                         case COMPRESSEDTEXFORMAT_ETC2_SRGB8:                                            return 8;
53                         case COMPRESSEDTEXFORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:         return 8;
54                         case COMPRESSEDTEXFORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:        return 8;
55                         case COMPRESSEDTEXFORMAT_ETC2_EAC_RGBA8:                                        return 16;
56                         case COMPRESSEDTEXFORMAT_ETC2_EAC_SRGB8_ALPHA8:                         return 16;
57
58                         default:
59                                 DE_ASSERT(false);
60                                 return -1;
61                 }
62         }
63         else if (isBcFormat(format))
64         {
65                 switch (format)
66                 {
67                         case COMPRESSEDTEXFORMAT_BC1_RGB_UNORM_BLOCK:                           return 8;
68                         case COMPRESSEDTEXFORMAT_BC1_RGB_SRGB_BLOCK:                            return 8;
69                         case COMPRESSEDTEXFORMAT_BC1_RGBA_UNORM_BLOCK:                          return 8;
70                         case COMPRESSEDTEXFORMAT_BC1_RGBA_SRGB_BLOCK:                           return 8;
71                         case COMPRESSEDTEXFORMAT_BC2_UNORM_BLOCK:                                       return 16;
72                         case COMPRESSEDTEXFORMAT_BC2_SRGB_BLOCK:                                        return 16;
73                         case COMPRESSEDTEXFORMAT_BC3_UNORM_BLOCK:                                       return 16;
74                         case COMPRESSEDTEXFORMAT_BC3_SRGB_BLOCK:                                        return 16;
75                         case COMPRESSEDTEXFORMAT_BC4_UNORM_BLOCK:                                       return 8;
76                         case COMPRESSEDTEXFORMAT_BC4_SNORM_BLOCK:                                       return 8;
77                         case COMPRESSEDTEXFORMAT_BC5_UNORM_BLOCK:                                       return 16;
78                         case COMPRESSEDTEXFORMAT_BC5_SNORM_BLOCK:                                       return 16;
79                         case COMPRESSEDTEXFORMAT_BC6H_UFLOAT_BLOCK:                                     return 16;
80                         case COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK:                                     return 16;
81                         case COMPRESSEDTEXFORMAT_BC7_UNORM_BLOCK:                                       return 16;
82                         case COMPRESSEDTEXFORMAT_BC7_SRGB_BLOCK:                                        return 16;
83
84                         default:
85                                 DE_ASSERT(false);
86                                 return -1;
87                 }
88         }
89         else
90         {
91                 DE_ASSERT(false);
92                 return -1;
93         }
94 }
95
96 IVec3 getBlockPixelSize (CompressedTexFormat format)
97 {
98         if (isEtcFormat(format))
99         {
100                 return IVec3(4, 4, 1);
101         }
102         else if (isAstcFormat(format))
103         {
104                 switch (format)
105                 {
106                         case COMPRESSEDTEXFORMAT_ASTC_4x4_RGBA:                         return IVec3(4,  4,  1);
107                         case COMPRESSEDTEXFORMAT_ASTC_5x4_RGBA:                         return IVec3(5,  4,  1);
108                         case COMPRESSEDTEXFORMAT_ASTC_5x5_RGBA:                         return IVec3(5,  5,  1);
109                         case COMPRESSEDTEXFORMAT_ASTC_6x5_RGBA:                         return IVec3(6,  5,  1);
110                         case COMPRESSEDTEXFORMAT_ASTC_6x6_RGBA:                         return IVec3(6,  6,  1);
111                         case COMPRESSEDTEXFORMAT_ASTC_8x5_RGBA:                         return IVec3(8,  5,  1);
112                         case COMPRESSEDTEXFORMAT_ASTC_8x6_RGBA:                         return IVec3(8,  6,  1);
113                         case COMPRESSEDTEXFORMAT_ASTC_8x8_RGBA:                         return IVec3(8,  8,  1);
114                         case COMPRESSEDTEXFORMAT_ASTC_10x5_RGBA:                        return IVec3(10, 5,  1);
115                         case COMPRESSEDTEXFORMAT_ASTC_10x6_RGBA:                        return IVec3(10, 6,  1);
116                         case COMPRESSEDTEXFORMAT_ASTC_10x8_RGBA:                        return IVec3(10, 8,  1);
117                         case COMPRESSEDTEXFORMAT_ASTC_10x10_RGBA:                       return IVec3(10, 10, 1);
118                         case COMPRESSEDTEXFORMAT_ASTC_12x10_RGBA:                       return IVec3(12, 10, 1);
119                         case COMPRESSEDTEXFORMAT_ASTC_12x12_RGBA:                       return IVec3(12, 12, 1);
120                         case COMPRESSEDTEXFORMAT_ASTC_4x4_SRGB8_ALPHA8:         return IVec3(4,  4,  1);
121                         case COMPRESSEDTEXFORMAT_ASTC_5x4_SRGB8_ALPHA8:         return IVec3(5,  4,  1);
122                         case COMPRESSEDTEXFORMAT_ASTC_5x5_SRGB8_ALPHA8:         return IVec3(5,  5,  1);
123                         case COMPRESSEDTEXFORMAT_ASTC_6x5_SRGB8_ALPHA8:         return IVec3(6,  5,  1);
124                         case COMPRESSEDTEXFORMAT_ASTC_6x6_SRGB8_ALPHA8:         return IVec3(6,  6,  1);
125                         case COMPRESSEDTEXFORMAT_ASTC_8x5_SRGB8_ALPHA8:         return IVec3(8,  5,  1);
126                         case COMPRESSEDTEXFORMAT_ASTC_8x6_SRGB8_ALPHA8:         return IVec3(8,  6,  1);
127                         case COMPRESSEDTEXFORMAT_ASTC_8x8_SRGB8_ALPHA8:         return IVec3(8,  8,  1);
128                         case COMPRESSEDTEXFORMAT_ASTC_10x5_SRGB8_ALPHA8:        return IVec3(10, 5,  1);
129                         case COMPRESSEDTEXFORMAT_ASTC_10x6_SRGB8_ALPHA8:        return IVec3(10, 6,  1);
130                         case COMPRESSEDTEXFORMAT_ASTC_10x8_SRGB8_ALPHA8:        return IVec3(10, 8,  1);
131                         case COMPRESSEDTEXFORMAT_ASTC_10x10_SRGB8_ALPHA8:       return IVec3(10, 10, 1);
132                         case COMPRESSEDTEXFORMAT_ASTC_12x10_SRGB8_ALPHA8:       return IVec3(12, 10, 1);
133                         case COMPRESSEDTEXFORMAT_ASTC_12x12_SRGB8_ALPHA8:       return IVec3(12, 12, 1);
134
135                         default:
136                                 DE_ASSERT(false);
137                                 return IVec3();
138                 }
139         }
140         else if (isBcFormat(format))
141         {
142                 return IVec3(4, 4, 1);
143         }
144         else
145         {
146                 DE_ASSERT(false);
147                 return IVec3(-1);
148         }
149 }
150
151 bool isEtcFormat (CompressedTexFormat format)
152 {
153         switch (format)
154         {
155                 case COMPRESSEDTEXFORMAT_ETC1_RGB8:
156                 case COMPRESSEDTEXFORMAT_EAC_R11:
157                 case COMPRESSEDTEXFORMAT_EAC_SIGNED_R11:
158                 case COMPRESSEDTEXFORMAT_EAC_RG11:
159                 case COMPRESSEDTEXFORMAT_EAC_SIGNED_RG11:
160                 case COMPRESSEDTEXFORMAT_ETC2_RGB8:
161                 case COMPRESSEDTEXFORMAT_ETC2_SRGB8:
162                 case COMPRESSEDTEXFORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
163                 case COMPRESSEDTEXFORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
164                 case COMPRESSEDTEXFORMAT_ETC2_EAC_RGBA8:
165                 case COMPRESSEDTEXFORMAT_ETC2_EAC_SRGB8_ALPHA8:
166                         return true;
167
168                 default:
169                         return false;
170         }
171 }
172
173 bool isBcFormat (CompressedTexFormat format)
174 {
175         switch (format)
176         {
177                 case COMPRESSEDTEXFORMAT_BC1_RGB_UNORM_BLOCK:
178                 case COMPRESSEDTEXFORMAT_BC1_RGB_SRGB_BLOCK:
179                 case COMPRESSEDTEXFORMAT_BC1_RGBA_UNORM_BLOCK:
180                 case COMPRESSEDTEXFORMAT_BC1_RGBA_SRGB_BLOCK:
181                 case COMPRESSEDTEXFORMAT_BC2_UNORM_BLOCK:
182                 case COMPRESSEDTEXFORMAT_BC2_SRGB_BLOCK:
183                 case COMPRESSEDTEXFORMAT_BC3_UNORM_BLOCK:
184                 case COMPRESSEDTEXFORMAT_BC3_SRGB_BLOCK:
185                 case COMPRESSEDTEXFORMAT_BC4_UNORM_BLOCK:
186                 case COMPRESSEDTEXFORMAT_BC4_SNORM_BLOCK:
187                 case COMPRESSEDTEXFORMAT_BC5_UNORM_BLOCK:
188                 case COMPRESSEDTEXFORMAT_BC5_SNORM_BLOCK:
189                 case COMPRESSEDTEXFORMAT_BC6H_UFLOAT_BLOCK:
190                 case COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK:
191                 case COMPRESSEDTEXFORMAT_BC7_UNORM_BLOCK:
192                 case COMPRESSEDTEXFORMAT_BC7_SRGB_BLOCK:
193                         return true;
194
195                 default:
196                         return false;
197         }
198 }
199
200 bool isBcBitExactFormat (CompressedTexFormat format)
201 {
202         switch (format)
203         {
204                 case COMPRESSEDTEXFORMAT_BC6H_UFLOAT_BLOCK:
205                 case COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK:
206                 case COMPRESSEDTEXFORMAT_BC7_UNORM_BLOCK:
207                 case COMPRESSEDTEXFORMAT_BC7_SRGB_BLOCK:
208                         return true;
209
210                 default:
211                         return false;
212         }
213 }
214
215 bool isBcSRGBFormat (CompressedTexFormat format)
216 {
217         switch (format)
218         {
219                 case COMPRESSEDTEXFORMAT_BC1_RGB_SRGB_BLOCK:
220                 case COMPRESSEDTEXFORMAT_BC1_RGBA_SRGB_BLOCK:
221                 case COMPRESSEDTEXFORMAT_BC2_SRGB_BLOCK:
222                 case COMPRESSEDTEXFORMAT_BC3_SRGB_BLOCK:
223                 case COMPRESSEDTEXFORMAT_BC7_SRGB_BLOCK:
224                         return true;
225
226                 default:
227                         return false;
228         }
229 }
230
231 bool isAstcFormat (CompressedTexFormat format)
232 {
233         switch (format)
234         {
235                 case COMPRESSEDTEXFORMAT_ASTC_4x4_RGBA:
236                 case COMPRESSEDTEXFORMAT_ASTC_5x4_RGBA:
237                 case COMPRESSEDTEXFORMAT_ASTC_5x5_RGBA:
238                 case COMPRESSEDTEXFORMAT_ASTC_6x5_RGBA:
239                 case COMPRESSEDTEXFORMAT_ASTC_6x6_RGBA:
240                 case COMPRESSEDTEXFORMAT_ASTC_8x5_RGBA:
241                 case COMPRESSEDTEXFORMAT_ASTC_8x6_RGBA:
242                 case COMPRESSEDTEXFORMAT_ASTC_8x8_RGBA:
243                 case COMPRESSEDTEXFORMAT_ASTC_10x5_RGBA:
244                 case COMPRESSEDTEXFORMAT_ASTC_10x6_RGBA:
245                 case COMPRESSEDTEXFORMAT_ASTC_10x8_RGBA:
246                 case COMPRESSEDTEXFORMAT_ASTC_10x10_RGBA:
247                 case COMPRESSEDTEXFORMAT_ASTC_12x10_RGBA:
248                 case COMPRESSEDTEXFORMAT_ASTC_12x12_RGBA:
249                 case COMPRESSEDTEXFORMAT_ASTC_4x4_SRGB8_ALPHA8:
250                 case COMPRESSEDTEXFORMAT_ASTC_5x4_SRGB8_ALPHA8:
251                 case COMPRESSEDTEXFORMAT_ASTC_5x5_SRGB8_ALPHA8:
252                 case COMPRESSEDTEXFORMAT_ASTC_6x5_SRGB8_ALPHA8:
253                 case COMPRESSEDTEXFORMAT_ASTC_6x6_SRGB8_ALPHA8:
254                 case COMPRESSEDTEXFORMAT_ASTC_8x5_SRGB8_ALPHA8:
255                 case COMPRESSEDTEXFORMAT_ASTC_8x6_SRGB8_ALPHA8:
256                 case COMPRESSEDTEXFORMAT_ASTC_8x8_SRGB8_ALPHA8:
257                 case COMPRESSEDTEXFORMAT_ASTC_10x5_SRGB8_ALPHA8:
258                 case COMPRESSEDTEXFORMAT_ASTC_10x6_SRGB8_ALPHA8:
259                 case COMPRESSEDTEXFORMAT_ASTC_10x8_SRGB8_ALPHA8:
260                 case COMPRESSEDTEXFORMAT_ASTC_10x10_SRGB8_ALPHA8:
261                 case COMPRESSEDTEXFORMAT_ASTC_12x10_SRGB8_ALPHA8:
262                 case COMPRESSEDTEXFORMAT_ASTC_12x12_SRGB8_ALPHA8:
263                         return true;
264
265                 default:
266                         return false;
267         }
268 }
269
270 bool isAstcSRGBFormat (CompressedTexFormat format)
271 {
272         switch (format)
273         {
274                 case COMPRESSEDTEXFORMAT_ASTC_4x4_SRGB8_ALPHA8:
275                 case COMPRESSEDTEXFORMAT_ASTC_5x4_SRGB8_ALPHA8:
276                 case COMPRESSEDTEXFORMAT_ASTC_5x5_SRGB8_ALPHA8:
277                 case COMPRESSEDTEXFORMAT_ASTC_6x5_SRGB8_ALPHA8:
278                 case COMPRESSEDTEXFORMAT_ASTC_6x6_SRGB8_ALPHA8:
279                 case COMPRESSEDTEXFORMAT_ASTC_8x5_SRGB8_ALPHA8:
280                 case COMPRESSEDTEXFORMAT_ASTC_8x6_SRGB8_ALPHA8:
281                 case COMPRESSEDTEXFORMAT_ASTC_8x8_SRGB8_ALPHA8:
282                 case COMPRESSEDTEXFORMAT_ASTC_10x5_SRGB8_ALPHA8:
283                 case COMPRESSEDTEXFORMAT_ASTC_10x6_SRGB8_ALPHA8:
284                 case COMPRESSEDTEXFORMAT_ASTC_10x8_SRGB8_ALPHA8:
285                 case COMPRESSEDTEXFORMAT_ASTC_10x10_SRGB8_ALPHA8:
286                 case COMPRESSEDTEXFORMAT_ASTC_12x10_SRGB8_ALPHA8:
287                 case COMPRESSEDTEXFORMAT_ASTC_12x12_SRGB8_ALPHA8:
288                         return true;
289
290                 default:
291                         return false;
292         }
293 }
294
295 TextureFormat getUncompressedFormat (CompressedTexFormat format)
296 {
297         if (isEtcFormat(format))
298         {
299                 switch (format)
300                 {
301                         case COMPRESSEDTEXFORMAT_ETC1_RGB8:                                                     return TextureFormat(TextureFormat::RGB,        TextureFormat::UNORM_INT8);
302                         case COMPRESSEDTEXFORMAT_EAC_R11:                                                       return TextureFormat(TextureFormat::R,          TextureFormat::UNORM_INT16);
303                         case COMPRESSEDTEXFORMAT_EAC_SIGNED_R11:                                        return TextureFormat(TextureFormat::R,          TextureFormat::SNORM_INT16);
304                         case COMPRESSEDTEXFORMAT_EAC_RG11:                                                      return TextureFormat(TextureFormat::RG,         TextureFormat::UNORM_INT16);
305                         case COMPRESSEDTEXFORMAT_EAC_SIGNED_RG11:                                       return TextureFormat(TextureFormat::RG,         TextureFormat::SNORM_INT16);
306                         case COMPRESSEDTEXFORMAT_ETC2_RGB8:                                                     return TextureFormat(TextureFormat::RGB,        TextureFormat::UNORM_INT8);
307                         case COMPRESSEDTEXFORMAT_ETC2_SRGB8:                                            return TextureFormat(TextureFormat::sRGB,       TextureFormat::UNORM_INT8);
308                         case COMPRESSEDTEXFORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:         return TextureFormat(TextureFormat::RGBA,       TextureFormat::UNORM_INT8);
309                         case COMPRESSEDTEXFORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:        return TextureFormat(TextureFormat::sRGBA,      TextureFormat::UNORM_INT8);
310                         case COMPRESSEDTEXFORMAT_ETC2_EAC_RGBA8:                                        return TextureFormat(TextureFormat::RGBA,       TextureFormat::UNORM_INT8);
311                         case COMPRESSEDTEXFORMAT_ETC2_EAC_SRGB8_ALPHA8:                         return TextureFormat(TextureFormat::sRGBA,      TextureFormat::UNORM_INT8);
312
313                         default:
314                                 DE_ASSERT(false);
315                                 return TextureFormat();
316                 }
317         }
318         else if (isAstcFormat(format))
319         {
320                 if (isAstcSRGBFormat(format))
321                         return TextureFormat(TextureFormat::sRGBA, TextureFormat::UNORM_INT8);
322                 else
323                         return TextureFormat(TextureFormat::RGBA, TextureFormat::HALF_FLOAT);
324         }
325         else if (isBcFormat(format))
326         {
327                 if (format == COMPRESSEDTEXFORMAT_BC4_UNORM_BLOCK || format == COMPRESSEDTEXFORMAT_BC4_SNORM_BLOCK)
328                         return TextureFormat(TextureFormat::R, TextureFormat::FLOAT);
329                 else if (format == COMPRESSEDTEXFORMAT_BC5_UNORM_BLOCK || format == COMPRESSEDTEXFORMAT_BC5_SNORM_BLOCK)
330                         return TextureFormat(TextureFormat::RG, TextureFormat::FLOAT);
331                 else if (format == COMPRESSEDTEXFORMAT_BC6H_UFLOAT_BLOCK || format == COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK)
332                         return TextureFormat(TextureFormat::RGB, TextureFormat::HALF_FLOAT);
333                 else if (isBcSRGBFormat(format))
334                         return TextureFormat(TextureFormat::sRGBA, TextureFormat::UNORM_INT8);
335                 else
336                         return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
337         }
338         else
339         {
340                 DE_ASSERT(false);
341                 return TextureFormat();
342         }
343 }
344
345 CompressedTexFormat getAstcFormatByBlockSize (const IVec3& size, bool isSRGB)
346 {
347         if (size.z() > 1)
348                 throw InternalError("3D ASTC textures not currently supported");
349
350         for (int fmtI = 0; fmtI < COMPRESSEDTEXFORMAT_LAST; fmtI++)
351         {
352                 const CompressedTexFormat fmt = (CompressedTexFormat)fmtI;
353
354                 if (isAstcFormat(fmt) && getBlockPixelSize(fmt) == size && isAstcSRGBFormat(fmt) == isSRGB)
355                         return fmt;
356         }
357
358         throw InternalError("Invalid ASTC block size " + de::toString(size.x()) + "x" + de::toString(size.y()) + "x" + de::toString(size.z()));
359 }
360
361 namespace
362 {
363
364 inline deUint8 extend4To8 (deUint8 src)
365 {
366         DE_ASSERT((src & ~((1<<4)-1)) == 0);
367         return (deUint8)((src << 4) | src);
368 }
369
370 inline deUint8 extend5To8 (deUint8 src)
371 {
372         DE_ASSERT((src & ~((1<<5)-1)) == 0);
373         return (deUint8)((src << 3) | (src >> 2));
374 }
375
376 inline deUint8 extend6To8 (deUint8 src)
377 {
378         DE_ASSERT((src & ~((1<<6)-1)) == 0);
379         return (deUint8)((src << 2) | (src >> 4));
380 }
381
382 // \todo [2013-08-06 nuutti] ETC and ASTC decompression codes are rather unrelated, and are already in their own "private" namespaces - should this be split to multiple files?
383
384 namespace EtcDecompressInternal
385 {
386
387 enum
388 {
389         ETC2_BLOCK_WIDTH                                        = 4,
390         ETC2_BLOCK_HEIGHT                                       = 4,
391         ETC2_UNCOMPRESSED_PIXEL_SIZE_A8         = 1,
392         ETC2_UNCOMPRESSED_PIXEL_SIZE_R11        = 2,
393         ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11       = 4,
394         ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8       = 3,
395         ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8      = 4,
396         ETC2_UNCOMPRESSED_BLOCK_SIZE_A8         = ETC2_BLOCK_WIDTH*ETC2_BLOCK_HEIGHT*ETC2_UNCOMPRESSED_PIXEL_SIZE_A8,
397         ETC2_UNCOMPRESSED_BLOCK_SIZE_R11        = ETC2_BLOCK_WIDTH*ETC2_BLOCK_HEIGHT*ETC2_UNCOMPRESSED_PIXEL_SIZE_R11,
398         ETC2_UNCOMPRESSED_BLOCK_SIZE_RG11       = ETC2_BLOCK_WIDTH*ETC2_BLOCK_HEIGHT*ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11,
399         ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8       = ETC2_BLOCK_WIDTH*ETC2_BLOCK_HEIGHT*ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8,
400         ETC2_UNCOMPRESSED_BLOCK_SIZE_RGBA8      = ETC2_BLOCK_WIDTH*ETC2_BLOCK_HEIGHT*ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8
401 };
402
403 inline deUint64 get64BitBlock (const deUint8* src, int blockNdx)
404 {
405         // Stored in big-endian form.
406         deUint64 block = 0;
407
408         for (int i = 0; i < 8; i++)
409                 block = (block << 8ull) | (deUint64)(src[blockNdx*8+i]);
410
411         return block;
412 }
413
414 // Return the first 64 bits of a 128 bit block.
415 inline deUint64 get128BitBlockStart (const deUint8* src, int blockNdx)
416 {
417         return get64BitBlock(src, 2*blockNdx);
418 }
419
420 // Return the last 64 bits of a 128 bit block.
421 inline deUint64 get128BitBlockEnd (const deUint8* src, int blockNdx)
422 {
423         return get64BitBlock(src, 2*blockNdx + 1);
424 }
425
426 inline deUint32 getBit (deUint64 src, int bit)
427 {
428         return (src >> bit) & 1;
429 }
430
431 inline deUint32 getBits (deUint64 src, int low, int high)
432 {
433         const int numBits = (high-low) + 1;
434         DE_ASSERT(de::inRange(numBits, 1, 32));
435         if (numBits < 32)
436                 return (deUint32)((src >> low) & ((1u<<numBits)-1));
437         else
438                 return (deUint32)((src >> low) & 0xFFFFFFFFu);
439 }
440
441 inline deUint8 extend7To8 (deUint8 src)
442 {
443         DE_ASSERT((src & ~((1<<7)-1)) == 0);
444         return (deUint8)((src << 1) | (src >> 6));
445 }
446
447 inline deInt8 extendSigned3To8 (deUint8 src)
448 {
449         const bool isNeg = (src & (1<<2)) != 0;
450         return (deInt8)((isNeg ? ~((1<<3)-1) : 0) | src);
451 }
452
453 inline deUint8 extend5Delta3To8 (deUint8 base5, deUint8 delta3)
454 {
455         const deUint8 t = (deUint8)((deInt8)base5 + extendSigned3To8(delta3));
456         return extend5To8(t);
457 }
458
459 inline deUint16 extend11To16 (deUint16 src)
460 {
461         DE_ASSERT((src & ~((1<<11)-1)) == 0);
462         return (deUint16)((src << 5) | (src >> 6));
463 }
464
465 inline deInt16 extend11To16WithSign (deInt16 src)
466 {
467         if (src < 0)
468                 return (deInt16)(-(deInt16)extend11To16((deUint16)(-src)));
469         else
470                 return (deInt16)extend11To16(src);
471 }
472
473 void decompressETC1Block (deUint8 dst[ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8], deUint64 src)
474 {
475         const int               diffBit         = (int)getBit(src, 33);
476         const int               flipBit         = (int)getBit(src, 32);
477         const deUint32  table[2]        = { getBits(src, 37, 39), getBits(src, 34, 36) };
478         deUint8                 baseR[2];
479         deUint8                 baseG[2];
480         deUint8                 baseB[2];
481
482         if (diffBit == 0)
483         {
484                 // Individual mode.
485                 baseR[0] = extend4To8((deUint8)getBits(src, 60, 63));
486                 baseR[1] = extend4To8((deUint8)getBits(src, 56, 59));
487                 baseG[0] = extend4To8((deUint8)getBits(src, 52, 55));
488                 baseG[1] = extend4To8((deUint8)getBits(src, 48, 51));
489                 baseB[0] = extend4To8((deUint8)getBits(src, 44, 47));
490                 baseB[1] = extend4To8((deUint8)getBits(src, 40, 43));
491         }
492         else
493         {
494                 // Differential mode (diffBit == 1).
495                 deUint8 bR = (deUint8)getBits(src, 59, 63); // 5b
496                 deUint8 dR = (deUint8)getBits(src, 56, 58); // 3b
497                 deUint8 bG = (deUint8)getBits(src, 51, 55);
498                 deUint8 dG = (deUint8)getBits(src, 48, 50);
499                 deUint8 bB = (deUint8)getBits(src, 43, 47);
500                 deUint8 dB = (deUint8)getBits(src, 40, 42);
501
502                 baseR[0] = extend5To8(bR);
503                 baseG[0] = extend5To8(bG);
504                 baseB[0] = extend5To8(bB);
505
506                 baseR[1] = extend5Delta3To8(bR, dR);
507                 baseG[1] = extend5Delta3To8(bG, dG);
508                 baseB[1] = extend5Delta3To8(bB, dB);
509         }
510
511         static const int modifierTable[8][4] =
512         {
513         //        00   01   10    11
514                 {  2,   8,  -2,   -8 },
515                 {  5,  17,  -5,  -17 },
516                 {  9,  29,  -9,  -29 },
517                 { 13,  42, -13,  -42 },
518                 { 18,  60, -18,  -60 },
519                 { 24,  80, -24,  -80 },
520                 { 33, 106, -33, -106 },
521                 { 47, 183, -47, -183 }
522         };
523
524         // Write final pixels.
525         for (int pixelNdx = 0; pixelNdx < ETC2_BLOCK_HEIGHT*ETC2_BLOCK_WIDTH; pixelNdx++)
526         {
527                 const int               x                               = pixelNdx / ETC2_BLOCK_HEIGHT;
528                 const int               y                               = pixelNdx % ETC2_BLOCK_HEIGHT;
529                 const int               dstOffset               = (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
530                 const int               subBlock                = ((flipBit ? y : x) >= 2) ? 1 : 0;
531                 const deUint32  tableNdx                = table[subBlock];
532                 const deUint32  modifierNdx             = (getBit(src, 16+pixelNdx) << 1) | getBit(src, pixelNdx);
533                 const int               modifier                = modifierTable[tableNdx][modifierNdx];
534
535                 dst[dstOffset+0] = (deUint8)deClamp32((int)baseR[subBlock] + modifier, 0, 255);
536                 dst[dstOffset+1] = (deUint8)deClamp32((int)baseG[subBlock] + modifier, 0, 255);
537                 dst[dstOffset+2] = (deUint8)deClamp32((int)baseB[subBlock] + modifier, 0, 255);
538         }
539 }
540
541 // if alphaMode is true, do PUNCHTHROUGH and store alpha to alphaDst; otherwise do ordinary ETC2 RGB8.
542 void decompressETC2Block (deUint8 dst[ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8], deUint64 src, deUint8 alphaDst[ETC2_UNCOMPRESSED_BLOCK_SIZE_A8], bool alphaMode)
543 {
544         enum Etc2Mode
545         {
546                 MODE_INDIVIDUAL = 0,
547                 MODE_DIFFERENTIAL,
548                 MODE_T,
549                 MODE_H,
550                 MODE_PLANAR,
551
552                 MODE_LAST
553         };
554
555         const int               diffOpaqueBit   = (int)getBit(src, 33);
556         const deInt8    selBR                   = (deInt8)getBits(src, 59, 63); // 5 bits.
557         const deInt8    selBG                   = (deInt8)getBits(src, 51, 55);
558         const deInt8    selBB                   = (deInt8)getBits(src, 43, 47);
559         const deInt8    selDR                   = extendSigned3To8((deUint8)getBits(src, 56, 58)); // 3 bits.
560         const deInt8    selDG                   = extendSigned3To8((deUint8)getBits(src, 48, 50));
561         const deInt8    selDB                   = extendSigned3To8((deUint8)getBits(src, 40, 42));
562         Etc2Mode                mode;
563
564         if (!alphaMode && diffOpaqueBit == 0)
565                 mode = MODE_INDIVIDUAL;
566         else if (!de::inRange(selBR + selDR, 0, 31))
567                 mode = MODE_T;
568         else if (!de::inRange(selBG + selDG, 0, 31))
569                 mode = MODE_H;
570         else if (!de::inRange(selBB + selDB, 0, 31))
571                 mode = MODE_PLANAR;
572         else
573                 mode = MODE_DIFFERENTIAL;
574
575         if (mode == MODE_INDIVIDUAL || mode == MODE_DIFFERENTIAL)
576         {
577                 // Individual and differential modes have some steps in common, handle them here.
578                 static const int modifierTable[8][4] =
579                 {
580                 //        00   01   10    11
581                         {  2,   8,  -2,   -8 },
582                         {  5,  17,  -5,  -17 },
583                         {  9,  29,  -9,  -29 },
584                         { 13,  42, -13,  -42 },
585                         { 18,  60, -18,  -60 },
586                         { 24,  80, -24,  -80 },
587                         { 33, 106, -33, -106 },
588                         { 47, 183, -47, -183 }
589                 };
590
591                 const int               flipBit         = (int)getBit(src, 32);
592                 const deUint32  table[2]        = { getBits(src, 37, 39), getBits(src, 34, 36) };
593                 deUint8                 baseR[2];
594                 deUint8                 baseG[2];
595                 deUint8                 baseB[2];
596
597                 if (mode == MODE_INDIVIDUAL)
598                 {
599                         // Individual mode, initial values.
600                         baseR[0] = extend4To8((deUint8)getBits(src, 60, 63));
601                         baseR[1] = extend4To8((deUint8)getBits(src, 56, 59));
602                         baseG[0] = extend4To8((deUint8)getBits(src, 52, 55));
603                         baseG[1] = extend4To8((deUint8)getBits(src, 48, 51));
604                         baseB[0] = extend4To8((deUint8)getBits(src, 44, 47));
605                         baseB[1] = extend4To8((deUint8)getBits(src, 40, 43));
606                 }
607                 else
608                 {
609                         // Differential mode, initial values.
610                         baseR[0] = extend5To8(selBR);
611                         baseG[0] = extend5To8(selBG);
612                         baseB[0] = extend5To8(selBB);
613
614                         baseR[1] = extend5To8((deUint8)(selBR + selDR));
615                         baseG[1] = extend5To8((deUint8)(selBG + selDG));
616                         baseB[1] = extend5To8((deUint8)(selBB + selDB));
617                 }
618
619                 // Write final pixels for individual or differential mode.
620                 for (int pixelNdx = 0; pixelNdx < ETC2_BLOCK_HEIGHT*ETC2_BLOCK_WIDTH; pixelNdx++)
621                 {
622                         const int               x                               = pixelNdx / ETC2_BLOCK_HEIGHT;
623                         const int               y                               = pixelNdx % ETC2_BLOCK_HEIGHT;
624                         const int               dstOffset               = (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
625                         const int               subBlock                = ((flipBit ? y : x) >= 2) ? 1 : 0;
626                         const deUint32  tableNdx                = table[subBlock];
627                         const deUint32  modifierNdx             = (getBit(src, 16+pixelNdx) << 1) | getBit(src, pixelNdx);
628                         const int               alphaDstOffset  = (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_A8; // Only needed for PUNCHTHROUGH version.
629
630                         // If doing PUNCHTHROUGH version (alphaMode), opaque bit may affect colors.
631                         if (alphaMode && diffOpaqueBit == 0 && modifierNdx == 2)
632                         {
633                                 dst[dstOffset+0]                        = 0;
634                                 dst[dstOffset+1]                        = 0;
635                                 dst[dstOffset+2]                        = 0;
636                                 alphaDst[alphaDstOffset]        = 0;
637                         }
638                         else
639                         {
640                                 int modifier;
641
642                                 // PUNCHTHROUGH version and opaque bit may also affect modifiers.
643                                 if (alphaMode && diffOpaqueBit == 0 && (modifierNdx == 0 || modifierNdx == 2))
644                                         modifier = 0;
645                                 else
646                                         modifier = modifierTable[tableNdx][modifierNdx];
647
648                                 dst[dstOffset+0] = (deUint8)deClamp32((int)baseR[subBlock] + modifier, 0, 255);
649                                 dst[dstOffset+1] = (deUint8)deClamp32((int)baseG[subBlock] + modifier, 0, 255);
650                                 dst[dstOffset+2] = (deUint8)deClamp32((int)baseB[subBlock] + modifier, 0, 255);
651
652                                 if (alphaMode)
653                                         alphaDst[alphaDstOffset] = 255;
654                         }
655                 }
656         }
657         else if (mode == MODE_T || mode == MODE_H)
658         {
659                 // T and H modes have some steps in common, handle them here.
660                 static const int distTable[8] = { 3, 6, 11, 16, 23, 32, 41, 64 };
661
662                 deUint8 paintR[4];
663                 deUint8 paintG[4];
664                 deUint8 paintB[4];
665
666                 if (mode == MODE_T)
667                 {
668                         // T mode, calculate paint values.
669                         const deUint8   R1a                     = (deUint8)getBits(src, 59, 60);
670                         const deUint8   R1b                     = (deUint8)getBits(src, 56, 57);
671                         const deUint8   G1                      = (deUint8)getBits(src, 52, 55);
672                         const deUint8   B1                      = (deUint8)getBits(src, 48, 51);
673                         const deUint8   R2                      = (deUint8)getBits(src, 44, 47);
674                         const deUint8   G2                      = (deUint8)getBits(src, 40, 43);
675                         const deUint8   B2                      = (deUint8)getBits(src, 36, 39);
676                         const deUint32  distNdx         = (getBits(src, 34, 35) << 1) | getBit(src, 32);
677                         const int               dist            = distTable[distNdx];
678
679                         paintR[0] = extend4To8((deUint8)((R1a << 2) | R1b));
680                         paintG[0] = extend4To8(G1);
681                         paintB[0] = extend4To8(B1);
682                         paintR[2] = extend4To8(R2);
683                         paintG[2] = extend4To8(G2);
684                         paintB[2] = extend4To8(B2);
685                         paintR[1] = (deUint8)deClamp32((int)paintR[2] + dist, 0, 255);
686                         paintG[1] = (deUint8)deClamp32((int)paintG[2] + dist, 0, 255);
687                         paintB[1] = (deUint8)deClamp32((int)paintB[2] + dist, 0, 255);
688                         paintR[3] = (deUint8)deClamp32((int)paintR[2] - dist, 0, 255);
689                         paintG[3] = (deUint8)deClamp32((int)paintG[2] - dist, 0, 255);
690                         paintB[3] = (deUint8)deClamp32((int)paintB[2] - dist, 0, 255);
691                 }
692                 else
693                 {
694                         // H mode, calculate paint values.
695                         const deUint8   R1              = (deUint8)getBits(src, 59, 62);
696                         const deUint8   G1a             = (deUint8)getBits(src, 56, 58);
697                         const deUint8   G1b             = (deUint8)getBit(src, 52);
698                         const deUint8   B1a             = (deUint8)getBit(src, 51);
699                         const deUint8   B1b             = (deUint8)getBits(src, 47, 49);
700                         const deUint8   R2              = (deUint8)getBits(src, 43, 46);
701                         const deUint8   G2              = (deUint8)getBits(src, 39, 42);
702                         const deUint8   B2              = (deUint8)getBits(src, 35, 38);
703                         deUint8                 baseR[2];
704                         deUint8                 baseG[2];
705                         deUint8                 baseB[2];
706                         deUint32                baseValue[2];
707                         deUint32                distNdx;
708                         int                             dist;
709
710                         baseR[0]                = extend4To8(R1);
711                         baseG[0]                = extend4To8((deUint8)((G1a << 1) | G1b));
712                         baseB[0]                = extend4To8((deUint8)((B1a << 3) | B1b));
713                         baseR[1]                = extend4To8(R2);
714                         baseG[1]                = extend4To8(G2);
715                         baseB[1]                = extend4To8(B2);
716                         baseValue[0]    = (((deUint32)baseR[0]) << 16) | (((deUint32)baseG[0]) << 8) | baseB[0];
717                         baseValue[1]    = (((deUint32)baseR[1]) << 16) | (((deUint32)baseG[1]) << 8) | baseB[1];
718                         distNdx                 = (getBit(src, 34) << 2) | (getBit(src, 32) << 1) | (deUint32)(baseValue[0] >= baseValue[1]);
719                         dist                    = distTable[distNdx];
720
721                         paintR[0]               = (deUint8)deClamp32((int)baseR[0] + dist, 0, 255);
722                         paintG[0]               = (deUint8)deClamp32((int)baseG[0] + dist, 0, 255);
723                         paintB[0]               = (deUint8)deClamp32((int)baseB[0] + dist, 0, 255);
724                         paintR[1]               = (deUint8)deClamp32((int)baseR[0] - dist, 0, 255);
725                         paintG[1]               = (deUint8)deClamp32((int)baseG[0] - dist, 0, 255);
726                         paintB[1]               = (deUint8)deClamp32((int)baseB[0] - dist, 0, 255);
727                         paintR[2]               = (deUint8)deClamp32((int)baseR[1] + dist, 0, 255);
728                         paintG[2]               = (deUint8)deClamp32((int)baseG[1] + dist, 0, 255);
729                         paintB[2]               = (deUint8)deClamp32((int)baseB[1] + dist, 0, 255);
730                         paintR[3]               = (deUint8)deClamp32((int)baseR[1] - dist, 0, 255);
731                         paintG[3]               = (deUint8)deClamp32((int)baseG[1] - dist, 0, 255);
732                         paintB[3]               = (deUint8)deClamp32((int)baseB[1] - dist, 0, 255);
733                 }
734
735                 // Write final pixels for T or H mode.
736                 for (int pixelNdx = 0; pixelNdx < ETC2_BLOCK_HEIGHT*ETC2_BLOCK_WIDTH; pixelNdx++)
737                 {
738                         const int               x                               = pixelNdx / ETC2_BLOCK_HEIGHT;
739                         const int               y                               = pixelNdx % ETC2_BLOCK_HEIGHT;
740                         const int               dstOffset               = (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
741                         const deUint32  paintNdx                = (getBit(src, 16+pixelNdx) << 1) | getBit(src, pixelNdx);
742                         const int               alphaDstOffset  = (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_A8; // Only needed for PUNCHTHROUGH version.
743
744                         if (alphaMode && diffOpaqueBit == 0 && paintNdx == 2)
745                         {
746                                 dst[dstOffset+0]                        = 0;
747                                 dst[dstOffset+1]                        = 0;
748                                 dst[dstOffset+2]                        = 0;
749                                 alphaDst[alphaDstOffset]        = 0;
750                         }
751                         else
752                         {
753                                 dst[dstOffset+0] = (deUint8)deClamp32((int)paintR[paintNdx], 0, 255);
754                                 dst[dstOffset+1] = (deUint8)deClamp32((int)paintG[paintNdx], 0, 255);
755                                 dst[dstOffset+2] = (deUint8)deClamp32((int)paintB[paintNdx], 0, 255);
756
757                                 if (alphaMode)
758                                         alphaDst[alphaDstOffset] = 255;
759                         }
760                 }
761         }
762         else
763         {
764                 // Planar mode.
765                 const deUint8 GO1       = (deUint8)getBit(src, 56);
766                 const deUint8 GO2       = (deUint8)getBits(src, 49, 54);
767                 const deUint8 BO1       = (deUint8)getBit(src, 48);
768                 const deUint8 BO2       = (deUint8)getBits(src, 43, 44);
769                 const deUint8 BO3       = (deUint8)getBits(src, 39, 41);
770                 const deUint8 RH1       = (deUint8)getBits(src, 34, 38);
771                 const deUint8 RH2       = (deUint8)getBit(src, 32);
772                 const deUint8 RO        = extend6To8((deUint8)getBits(src, 57, 62));
773                 const deUint8 GO        = extend7To8((deUint8)((GO1 << 6) | GO2));
774                 const deUint8 BO        = extend6To8((deUint8)((BO1 << 5) | (BO2 << 3) | BO3));
775                 const deUint8 RH        = extend6To8((deUint8)((RH1 << 1) | RH2));
776                 const deUint8 GH        = extend7To8((deUint8)getBits(src, 25, 31));
777                 const deUint8 BH        = extend6To8((deUint8)getBits(src, 19, 24));
778                 const deUint8 RV        = extend6To8((deUint8)getBits(src, 13, 18));
779                 const deUint8 GV        = extend7To8((deUint8)getBits(src, 6, 12));
780                 const deUint8 BV        = extend6To8((deUint8)getBits(src, 0, 5));
781
782                 // Write final pixels for planar mode.
783                 for (int y = 0; y < 4; y++)
784                 {
785                         for (int x = 0; x < 4; x++)
786                         {
787                                 const int dstOffset                     = (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
788                                 const int unclampedR            = (x * ((int)RH-(int)RO) + y * ((int)RV-(int)RO) + 4*(int)RO + 2) >> 2;
789                                 const int unclampedG            = (x * ((int)GH-(int)GO) + y * ((int)GV-(int)GO) + 4*(int)GO + 2) >> 2;
790                                 const int unclampedB            = (x * ((int)BH-(int)BO) + y * ((int)BV-(int)BO) + 4*(int)BO + 2) >> 2;
791                                 const int alphaDstOffset        = (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_A8; // Only needed for PUNCHTHROUGH version.
792
793                                 dst[dstOffset+0] = (deUint8)deClamp32(unclampedR, 0, 255);
794                                 dst[dstOffset+1] = (deUint8)deClamp32(unclampedG, 0, 255);
795                                 dst[dstOffset+2] = (deUint8)deClamp32(unclampedB, 0, 255);
796
797                                 if (alphaMode)
798                                         alphaDst[alphaDstOffset] = 255;
799                         }
800                 }
801         }
802 }
803
804 void decompressEAC8Block (deUint8 dst[ETC2_UNCOMPRESSED_BLOCK_SIZE_A8], deUint64 src)
805 {
806         static const int modifierTable[16][8] =
807         {
808                 {-3,  -6,  -9, -15,  2,  5,  8, 14},
809                 {-3,  -7, -10, -13,  2,  6,  9, 12},
810                 {-2,  -5,  -8, -13,  1,  4,  7, 12},
811                 {-2,  -4,  -6, -13,  1,  3,  5, 12},
812                 {-3,  -6,  -8, -12,  2,  5,  7, 11},
813                 {-3,  -7,  -9, -11,  2,  6,  8, 10},
814                 {-4,  -7,  -8, -11,  3,  6,  7, 10},
815                 {-3,  -5,  -8, -11,  2,  4,  7, 10},
816                 {-2,  -6,  -8, -10,  1,  5,  7,  9},
817                 {-2,  -5,  -8, -10,  1,  4,  7,  9},
818                 {-2,  -4,  -8, -10,  1,  3,  7,  9},
819                 {-2,  -5,  -7, -10,  1,  4,  6,  9},
820                 {-3,  -4,  -7, -10,  2,  3,  6,  9},
821                 {-1,  -2,  -3, -10,  0,  1,  2,  9},
822                 {-4,  -6,  -8,  -9,  3,  5,  7,  8},
823                 {-3,  -5,  -7,  -9,  2,  4,  6,  8}
824         };
825
826         const deUint8   baseCodeword    = (deUint8)getBits(src, 56, 63);
827         const deUint8   multiplier              = (deUint8)getBits(src, 52, 55);
828         const deUint32  tableNdx                = getBits(src, 48, 51);
829
830         for (int pixelNdx = 0; pixelNdx < ETC2_BLOCK_HEIGHT*ETC2_BLOCK_WIDTH; pixelNdx++)
831         {
832                 const int               x                               = pixelNdx / ETC2_BLOCK_HEIGHT;
833                 const int               y                               = pixelNdx % ETC2_BLOCK_HEIGHT;
834                 const int               dstOffset               = (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_A8;
835                 const int               pixelBitNdx             = 45 - 3*pixelNdx;
836                 const deUint32  modifierNdx             = (getBit(src, pixelBitNdx + 2) << 2) | (getBit(src, pixelBitNdx + 1) << 1) | getBit(src, pixelBitNdx);
837                 const int               modifier                = modifierTable[tableNdx][modifierNdx];
838
839                 dst[dstOffset] = (deUint8)deClamp32((int)baseCodeword + (int)multiplier*modifier, 0, 255);
840         }
841 }
842
843 void decompressEAC11Block (deUint8 dst[ETC2_UNCOMPRESSED_BLOCK_SIZE_R11], deUint64 src, bool signedMode)
844 {
845         static const int modifierTable[16][8] =
846         {
847                 {-3,  -6,  -9, -15,  2,  5,  8, 14},
848                 {-3,  -7, -10, -13,  2,  6,  9, 12},
849                 {-2,  -5,  -8, -13,  1,  4,  7, 12},
850                 {-2,  -4,  -6, -13,  1,  3,  5, 12},
851                 {-3,  -6,  -8, -12,  2,  5,  7, 11},
852                 {-3,  -7,  -9, -11,  2,  6,  8, 10},
853                 {-4,  -7,  -8, -11,  3,  6,  7, 10},
854                 {-3,  -5,  -8, -11,  2,  4,  7, 10},
855                 {-2,  -6,  -8, -10,  1,  5,  7,  9},
856                 {-2,  -5,  -8, -10,  1,  4,  7,  9},
857                 {-2,  -4,  -8, -10,  1,  3,  7,  9},
858                 {-2,  -5,  -7, -10,  1,  4,  6,  9},
859                 {-3,  -4,  -7, -10,  2,  3,  6,  9},
860                 {-1,  -2,  -3, -10,  0,  1,  2,  9},
861                 {-4,  -6,  -8,  -9,  3,  5,  7,  8},
862                 {-3,  -5,  -7,  -9,  2,  4,  6,  8}
863         };
864
865         const deInt32 multiplier        = (deInt32)getBits(src, 52, 55);
866         const deInt32 tableNdx          = (deInt32)getBits(src, 48, 51);
867         deInt32 baseCodeword            = (deInt32)getBits(src, 56, 63);
868
869         if (signedMode)
870         {
871                 if (baseCodeword > 127)
872                         baseCodeword -= 256;
873                 if (baseCodeword == -128)
874                         baseCodeword = -127;
875         }
876
877         for (int pixelNdx = 0; pixelNdx < ETC2_BLOCK_HEIGHT*ETC2_BLOCK_WIDTH; pixelNdx++)
878         {
879                 const int               x                               = pixelNdx / ETC2_BLOCK_HEIGHT;
880                 const int               y                               = pixelNdx % ETC2_BLOCK_HEIGHT;
881                 const int               dstOffset               = (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_R11;
882                 const int               pixelBitNdx             = 45 - 3*pixelNdx;
883                 const deUint32  modifierNdx             = (getBit(src, pixelBitNdx + 2) << 2) | (getBit(src, pixelBitNdx + 1) << 1) | getBit(src, pixelBitNdx);
884                 const int               modifier                = modifierTable[tableNdx][modifierNdx];
885
886                 if (signedMode)
887                 {
888                         deInt16 value;
889
890                         if (multiplier != 0)
891                                 value = (deInt16)deClamp32(baseCodeword*8 + multiplier*modifier*8, -1023, 1023);
892                         else
893                                 value = (deInt16)deClamp32(baseCodeword*8 + modifier, -1023, 1023);
894
895                         *((deInt16*)(dst + dstOffset)) = value;
896                 }
897                 else
898                 {
899                         deUint16 value;
900
901                         if (multiplier != 0)
902                                 value = (deUint16)deClamp32(baseCodeword*8 + 4 + multiplier*modifier*8, 0, 2047);
903                         else
904                                 value= (deUint16)deClamp32(baseCodeword*8 + 4 + modifier, 0, 2047);
905
906                         *((deUint16*)(dst + dstOffset)) = value;
907                 }
908         }
909 }
910
911 } // EtcDecompressInternal
912
913 void decompressETC1 (const PixelBufferAccess& dst, const deUint8* src)
914 {
915         using namespace EtcDecompressInternal;
916
917         deUint8* const  dstPtr                  = (deUint8*)dst.getDataPtr();
918         const deUint64  compressedBlock = get64BitBlock(src, 0);
919
920         decompressETC1Block(dstPtr, compressedBlock);
921 }
922
923 void decompressETC2 (const PixelBufferAccess& dst, const deUint8* src)
924 {
925         using namespace EtcDecompressInternal;
926
927         deUint8* const  dstPtr                  = (deUint8*)dst.getDataPtr();
928         const deUint64  compressedBlock = get64BitBlock(src, 0);
929
930         decompressETC2Block(dstPtr, compressedBlock, NULL, false);
931 }
932
933 void decompressETC2_EAC_RGBA8 (const PixelBufferAccess& dst, const deUint8* src)
934 {
935         using namespace EtcDecompressInternal;
936
937         deUint8* const  dstPtr                  = (deUint8*)dst.getDataPtr();
938         const int               dstRowPitch             = dst.getRowPitch();
939         const int               dstPixelSize    = ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8;
940
941         const deUint64  compressedBlockAlpha    = get128BitBlockStart(src, 0);
942         const deUint64  compressedBlockRGB              = get128BitBlockEnd(src, 0);
943         deUint8                 uncompressedBlockAlpha[ETC2_UNCOMPRESSED_BLOCK_SIZE_A8];
944         deUint8                 uncompressedBlockRGB[ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8];
945
946         // Decompress.
947         decompressETC2Block(uncompressedBlockRGB, compressedBlockRGB, NULL, false);
948         decompressEAC8Block(uncompressedBlockAlpha, compressedBlockAlpha);
949
950         // Write to dst.
951         for (int y = 0; y < (int)ETC2_BLOCK_HEIGHT; y++)
952         {
953                 for (int x = 0; x < (int)ETC2_BLOCK_WIDTH; x++)
954                 {
955                         const deUint8* const    srcPixelRGB             = &uncompressedBlockRGB[(y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8];
956                         const deUint8* const    srcPixelAlpha   = &uncompressedBlockAlpha[(y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_A8];
957                         deUint8* const                  dstPixel                = dstPtr + y*dstRowPitch + x*dstPixelSize;
958
959                         DE_STATIC_ASSERT(ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8 == 4);
960                         dstPixel[0] = srcPixelRGB[0];
961                         dstPixel[1] = srcPixelRGB[1];
962                         dstPixel[2] = srcPixelRGB[2];
963                         dstPixel[3] = srcPixelAlpha[0];
964                 }
965         }
966 }
967
968 void decompressETC2_RGB8_PUNCHTHROUGH_ALPHA1 (const PixelBufferAccess& dst, const deUint8* src)
969 {
970         using namespace EtcDecompressInternal;
971
972         deUint8* const  dstPtr                  = (deUint8*)dst.getDataPtr();
973         const int               dstRowPitch             = dst.getRowPitch();
974         const int               dstPixelSize    = ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8;
975
976         const deUint64  compressedBlockRGBA     = get64BitBlock(src, 0);
977         deUint8                 uncompressedBlockRGB[ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8];
978         deUint8                 uncompressedBlockAlpha[ETC2_UNCOMPRESSED_BLOCK_SIZE_A8];
979
980         // Decompress.
981         decompressETC2Block(uncompressedBlockRGB, compressedBlockRGBA, uncompressedBlockAlpha, DE_TRUE);
982
983         // Write to dst.
984         for (int y = 0; y < (int)ETC2_BLOCK_HEIGHT; y++)
985         {
986                 for (int x = 0; x < (int)ETC2_BLOCK_WIDTH; x++)
987                 {
988                         const deUint8* const    srcPixel                = &uncompressedBlockRGB[(y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8];
989                         const deUint8* const    srcPixelAlpha   = &uncompressedBlockAlpha[(y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_A8];
990                         deUint8* const                  dstPixel                = dstPtr + y*dstRowPitch + x*dstPixelSize;
991
992                         DE_STATIC_ASSERT(ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8 == 4);
993                         dstPixel[0] = srcPixel[0];
994                         dstPixel[1] = srcPixel[1];
995                         dstPixel[2] = srcPixel[2];
996                         dstPixel[3] = srcPixelAlpha[0];
997                 }
998         }
999 }
1000
1001 void decompressEAC_R11 (const PixelBufferAccess& dst, const deUint8* src, bool signedMode)
1002 {
1003         using namespace EtcDecompressInternal;
1004
1005         deUint8* const  dstPtr                  = (deUint8*)dst.getDataPtr();
1006         const int               dstRowPitch             = dst.getRowPitch();
1007         const int               dstPixelSize    = ETC2_UNCOMPRESSED_PIXEL_SIZE_R11;
1008
1009         const deUint64  compressedBlock = get64BitBlock(src, 0);
1010         deUint8                 uncompressedBlock[ETC2_UNCOMPRESSED_BLOCK_SIZE_R11];
1011
1012         // Decompress.
1013         decompressEAC11Block(uncompressedBlock, compressedBlock, signedMode);
1014
1015         // Write to dst.
1016         for (int y = 0; y < (int)ETC2_BLOCK_HEIGHT; y++)
1017         {
1018                 for (int x = 0; x < (int)ETC2_BLOCK_WIDTH; x++)
1019                 {
1020                         DE_STATIC_ASSERT(ETC2_UNCOMPRESSED_PIXEL_SIZE_R11 == 2);
1021
1022                         if (signedMode)
1023                         {
1024                                 const deInt16* const    srcPixel = (deInt16*)&uncompressedBlock[(y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_R11];
1025                                 deInt16* const                  dstPixel = (deInt16*)(dstPtr + y*dstRowPitch + x*dstPixelSize);
1026
1027                                 dstPixel[0] = extend11To16WithSign(srcPixel[0]);
1028                         }
1029                         else
1030                         {
1031                                 const deUint16* const   srcPixel = (deUint16*)&uncompressedBlock[(y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_R11];
1032                                 deUint16* const                 dstPixel = (deUint16*)(dstPtr + y*dstRowPitch + x*dstPixelSize);
1033
1034                                 dstPixel[0] = extend11To16(srcPixel[0]);
1035                         }
1036                 }
1037         }
1038 }
1039
1040 void decompressEAC_RG11 (const PixelBufferAccess& dst, const deUint8* src, bool signedMode)
1041 {
1042         using namespace EtcDecompressInternal;
1043
1044         deUint8* const  dstPtr                  = (deUint8*)dst.getDataPtr();
1045         const int               dstRowPitch             = dst.getRowPitch();
1046         const int               dstPixelSize    = ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11;
1047
1048         const deUint64  compressedBlockR = get128BitBlockStart(src, 0);
1049         const deUint64  compressedBlockG = get128BitBlockEnd(src, 0);
1050         deUint8                 uncompressedBlockR[ETC2_UNCOMPRESSED_BLOCK_SIZE_R11];
1051         deUint8                 uncompressedBlockG[ETC2_UNCOMPRESSED_BLOCK_SIZE_R11];
1052
1053         // Decompress.
1054         decompressEAC11Block(uncompressedBlockR, compressedBlockR, signedMode);
1055         decompressEAC11Block(uncompressedBlockG, compressedBlockG, signedMode);
1056
1057         // Write to dst.
1058         for (int y = 0; y < (int)ETC2_BLOCK_HEIGHT; y++)
1059         {
1060                 for (int x = 0; x < (int)ETC2_BLOCK_WIDTH; x++)
1061                 {
1062                         DE_STATIC_ASSERT(ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11 == 4);
1063
1064                         if (signedMode)
1065                         {
1066                                 const deInt16* const    srcPixelR       = (deInt16*)&uncompressedBlockR[(y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_R11];
1067                                 const deInt16* const    srcPixelG       = (deInt16*)&uncompressedBlockG[(y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_R11];
1068                                 deInt16* const                  dstPixel        = (deInt16*)(dstPtr + y*dstRowPitch + x*dstPixelSize);
1069
1070                                 dstPixel[0] = extend11To16WithSign(srcPixelR[0]);
1071                                 dstPixel[1] = extend11To16WithSign(srcPixelG[0]);
1072                         }
1073                         else
1074                         {
1075                                 const deUint16* const   srcPixelR       = (deUint16*)&uncompressedBlockR[(y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_R11];
1076                                 const deUint16* const   srcPixelG       = (deUint16*)&uncompressedBlockG[(y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_R11];
1077                                 deUint16* const                 dstPixel        = (deUint16*)(dstPtr + y*dstRowPitch + x*dstPixelSize);
1078
1079                                 dstPixel[0] = extend11To16(srcPixelR[0]);
1080                                 dstPixel[1] = extend11To16(srcPixelG[0]);
1081                         }
1082                 }
1083         }
1084 }
1085
1086 namespace BcDecompressInternal
1087 {
1088
1089 enum
1090 {
1091         BC_BLOCK_WIDTH  = 4,
1092         BC_BLOCK_HEIGHT = 4
1093 };
1094
1095 static const deUint8    epBits[14]                                              = { 10, 7, 11, 11, 11, 9, 8, 8, 8, 6, 10, 11, 12, 16 };
1096
1097 static const deUint8    partitions2[64][16]                             =
1098 {
1099         { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 },
1100         { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 },
1101         { 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 },
1102         { 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1 },
1103         { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1 },
1104         { 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
1105         { 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
1106         { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1 },
1107         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1 },
1108         { 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
1109         { 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
1110         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1 },
1111         { 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
1112         { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
1113         { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
1114         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 },
1115         { 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1 },
1116         { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
1117         { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0 },
1118         { 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0 },
1119         { 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
1120         { 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0 },
1121         { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 },
1122         { 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1 },
1123         { 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 },
1124         { 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 },
1125         { 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0 },
1126         { 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0 },
1127         { 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0 },
1128         { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
1129         { 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0 },
1130         { 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0 },
1131         { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 },
1132         { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 },
1133         { 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0 },
1134         { 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0 },
1135         { 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0 },
1136         { 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0 },
1137         { 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1 },
1138         { 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1 },
1139         { 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0 },
1140         { 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0 },
1141         { 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 },
1142         { 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0 },
1143         { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 },
1144         { 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1 },
1145         { 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1 },
1146         { 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
1147         { 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
1148         { 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0 },
1149         { 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0 },
1150         { 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0 },
1151         { 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 },
1152         { 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1 },
1153         { 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0 },
1154         { 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0 },
1155         { 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1 },
1156         { 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1 },
1157         { 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 },
1158         { 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1 },
1159         { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 },
1160         { 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
1161         { 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0 },
1162         { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1 }
1163 };
1164
1165 static const deUint8    partitions3[64][16]                             =
1166 {
1167         { 0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 1, 2, 2, 2, 2 },
1168         { 0, 0, 0, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1 },
1169         { 0, 0, 0, 0, 2, 0, 0, 1, 2, 2, 1, 1, 2, 2, 1, 1 },
1170         { 0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 1, 0, 1, 1, 1 },
1171         { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2 },
1172         { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 2, 2 },
1173         { 0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 },
1174         { 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1 },
1175         { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2 },
1176         { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2 },
1177         { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2 },
1178         { 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2 },
1179         { 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2 },
1180         { 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2 },
1181         { 0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2 },
1182         { 0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0, 2, 2, 2, 0 },
1183         { 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2 },
1184         { 0, 1, 1, 1, 0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0 },
1185         { 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2 },
1186         { 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1 },
1187         { 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2 },
1188         { 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, 2, 1, 2, 2, 2, 1 },
1189         { 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2 },
1190         { 0, 0, 0, 0, 1, 1, 0, 0, 2, 2, 1, 0, 2, 2, 1, 0 },
1191         { 0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1, 0, 0, 0, 0 },
1192         { 0, 0, 1, 2, 0, 0, 1, 2, 1, 1, 2, 2, 2, 2, 2, 2 },
1193         { 0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1, 0, 1, 1, 0 },
1194         { 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1 },
1195         { 0, 0, 2, 2, 1, 1, 0, 2, 1, 1, 0, 2, 0, 0, 2, 2 },
1196         { 0, 1, 1, 0, 0, 1, 1, 0, 2, 0, 0, 2, 2, 2, 2, 2 },
1197         { 0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1 },
1198         { 0, 0, 0, 0, 2, 0, 0, 0, 2, 2, 1, 1, 2, 2, 2, 1 },
1199         { 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 2, 2, 2 },
1200         { 0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 2, 0, 0, 1, 1 },
1201         { 0, 0, 1, 1, 0, 0, 1, 2, 0, 0, 2, 2, 0, 2, 2, 2 },
1202         { 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0 },
1203         { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0 },
1204         { 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0 },
1205         { 0, 1, 2, 0, 2, 0, 1, 2, 1, 2, 0, 1, 0, 1, 2, 0 },
1206         { 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2, 0, 0, 1, 1 },
1207         { 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 1, 1 },
1208         { 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2 },
1209         { 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1 },
1210         { 0, 0, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2, 1, 1, 2, 2 },
1211         { 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 1, 1 },
1212         { 0, 2, 2, 0, 1, 2, 2, 1, 0, 2, 2, 0, 1, 2, 2, 1 },
1213         { 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 1 },
1214         { 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1 },
1215         { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2 },
1216         { 0, 2, 2, 2, 0, 1, 1, 1, 0, 2, 2, 2, 0, 1, 1, 1 },
1217         { 0, 0, 0, 2, 1, 1, 1, 2, 0, 0, 0, 2, 1, 1, 1, 2 },
1218         { 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2 },
1219         { 0, 2, 2, 2, 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2 },
1220         { 0, 0, 0, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2 },
1221         { 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2 },
1222         { 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2 },
1223         { 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2 },
1224         { 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2 },
1225         { 0, 0, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2 },
1226         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2 },
1227         { 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1 },
1228         { 0, 2, 2, 2, 1, 2, 2, 2, 0, 2, 2, 2, 1, 2, 2, 2 },
1229         { 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
1230         { 0, 1, 1, 1, 2, 0, 1, 1, 2, 2, 0, 1, 2, 2, 2, 0 }
1231 };
1232
1233 static const deUint8    anchorIndicesSecondSubset2[64]  = {     15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 8, 2, 2, 8, 8, 15, 2, 8, 2, 2, 8, 8, 2, 2,
1234                                                                                                                         15, 15, 6, 8, 2, 8, 15, 15, 2, 8, 2, 2, 2, 15, 15, 6, 6, 2, 6, 8, 15, 15, 2, 2, 15, 15, 15, 15, 15, 2, 2, 15 };
1235
1236 static const deUint8    anchorIndicesSecondSubset3[64]  = {     3, 3, 15, 15, 8, 3, 15, 15, 8, 8, 6, 6, 6, 5, 3, 3, 3, 3, 8, 15, 3, 3, 6, 10, 5, 8, 8, 6, 8, 5, 15, 15,
1237                                                                                                                         8, 15, 3, 5, 6, 10, 8, 15, 15, 3, 15, 5, 15, 15, 15, 15, 3, 15, 5, 5, 5, 8, 5, 10, 5, 10, 8, 13, 15, 12, 3, 3 };
1238
1239 static const deUint8    anchorIndicesThirdSubset[64]    = {     15, 8, 8, 3, 15, 15, 3, 8, 15, 15, 15, 15, 15, 15, 15, 8, 15, 8, 15, 3, 15, 8, 15, 8, 3, 15, 6, 10, 15, 15, 10, 8,
1240                                                                                                                         15, 3, 15, 10, 10, 8, 9, 10, 6, 15, 8, 15, 3, 6, 6, 8, 15, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 15, 15, 8 };
1241
1242 static const deUint16   weights2[4]                                             = { 0, 21, 43, 64 };
1243 static const deUint16   weights3[8]                                             = { 0, 9, 18, 27, 37, 46, 55, 64 };
1244 static const deUint16   weights4[16]                                    = { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 };
1245
1246 inline float uint8ToFloat (deUint8 src)
1247 {
1248         return ((float)src / 255.0f);
1249 }
1250
1251 inline float int8ToFloat (deInt8 src)
1252 {
1253         return ((float)src / 128.0f);
1254 }
1255
1256 inline deUint32 bgr16torgba32 (deUint16 src)
1257 {
1258         const deUint32  src32   = src;
1259         const deUint8   b5              = (src32 & 0x1f);
1260         const deUint8   g6              = (src32 >> 5) & 0x3f;
1261         const deUint8   r5              = (src32 >> 11) & 0x1f;
1262         const deUint32  a8              = 0xff;
1263         const deUint32  b8              = extend5To8(b5);
1264         const deUint32  g8              = extend6To8(g6);
1265         const deUint32  r8              = extend5To8(r5);
1266
1267         return (r8 | (g8 <<8) | (b8 << 16) | (a8 << 24));
1268 }
1269
1270 // Interpolates color = 1/3 * c0 + 2/3 * c1
1271 inline deUint32 interpolateColor (deUint32 c0, deUint32 c1)
1272 {
1273         const deUint32  r0      = c0 & 0xff;
1274         const deUint32  g0      = (c0 >> 8) & 0xff;
1275         const deUint32  b0      = (c0 >> 16) & 0xff;
1276         const deUint32  a0      = (c0 >> 24) & 0xff;
1277
1278         const deUint32  r1      = c1 & 0xff;
1279         const deUint32  g1      = (c1 >> 8) & 0xff;
1280         const deUint32  b1      = (c1 >> 16) & 0xff;
1281         const deUint32  a1      = (c1 >> 24) & 0xff;
1282
1283         const deUint32  r       = (r0 + (r1 << 1)) / 3;
1284         const deUint32  g       = (g0 + (g1 << 1)) / 3;
1285         const deUint32  b       = (b0 + (b1 << 1)) / 3;
1286         const deUint32  a       = (a0 + (a1 << 1)) / 3;
1287
1288         return (r | (g << 8) | (b << 16) | (a << 24));
1289 }
1290
1291 // Average of two colors
1292 inline deUint32 averageColor (deUint32 c0, deUint32 c1)
1293 {
1294         const deUint32  r0      = c0 & 0xff;
1295         const deUint32  g0      = (c0 >> 8) & 0xff;
1296         const deUint32  b0      = (c0 >> 16) & 0xff;
1297         const deUint32  a0      = (c0 >> 24) & 0xff;
1298
1299         const deUint32  r1      = c1 & 0xff;
1300         const deUint32  g1      = (c1 >> 8) & 0xff;
1301         const deUint32  b1      = (c1 >> 16) & 0xff;
1302         const deUint32  a1      = (c1 >> 24) & 0xff;
1303
1304         const deUint32  r       = (r0 + r1) >> 1;
1305         const deUint32  g       = (g0 + g1) >> 1;
1306         const deUint32  b       = (b0 + b1) >> 1;
1307         const deUint32  a       = (a0 + a1) >> 1;
1308
1309         return (r | (g << 8) | (b << 16) | (a << 24));
1310 }
1311
1312 inline deInt8 extractModeBc6 (deUint8 src)
1313 {
1314         // Catch illegal modes
1315         switch(src & 0x1f)
1316         {
1317                 case 0x13:
1318                 case 0x17:
1319                 case 0x1b:
1320                 case 0x1f:
1321                         return -1;
1322         };
1323
1324         switch (src & 0x3)
1325         {
1326                 case 0: return 0;
1327                 case 1: return 1;
1328                 case 2: return (deInt8)(2 + ((src >> 2) & 0x7));
1329                 case 3: return (deInt8)(10 + ((src >> 2) & 0x7));
1330         };
1331
1332         return -1;
1333 }
1334
1335 inline deInt8 extractModeBc7 (deUint8 src)
1336 {
1337         for (deInt8 i = 0; i < 8; i++)
1338                 if (src & (1 << i))
1339                         return i;
1340
1341         return -1;
1342 }
1343
1344 inline deUint64 get64BitBlockLE (const deUint8* src, int blockNdx)
1345 {
1346         // Same as get64BitBlock, but little-endian.
1347         deUint64 block = 0;
1348
1349         for (int i = 0; i < 8; i++)
1350                 block |= (deUint64)(src[blockNdx*8+i]) << (8ull*i);
1351
1352         return block;
1353 }
1354
1355 inline deUint32 getBits128 (deUint64 low, deUint64 high, deUint32 first, deUint32 last)
1356 {
1357         const deUint64  d[2]    = { low, high };
1358         const bool              reverse = first > last;
1359         deUint32                ret             = 0;
1360
1361         if (reverse)
1362         {
1363                 const deUint32 tmp = first;
1364                 first = last;
1365                 last = tmp;
1366         }
1367
1368         const int       elementFirst    = first / 64;
1369         const int       elementLast             = last / 64;
1370
1371         if (elementFirst == elementLast)
1372         {
1373                 // Bits contained in one of the 64bit elements
1374                 const deUint32 shift = first % 64;
1375                 const deUint32 len = last - first + 1;
1376                 const deUint32 mask = (1 << len) - 1;
1377                 ret = (deUint32)((d[elementFirst] >> shift) & mask);
1378         }
1379         else
1380         {
1381                 // Bits contained in both of the 64bit elements
1382                 DE_ASSERT(last > 63);
1383                 DE_ASSERT(first < 64);
1384                 const deUint32 len0 = 64 - first;
1385                 const deUint32 mask0 = (1 << len0) - 1;
1386                 const deUint32 data0 = (deUint32)(low >> first) & mask0;
1387                 const deUint32 len1 = last - 63;
1388                 const deUint32 mask1 = (1 << len1) - 1;
1389                 const deUint32 data1 = (deUint32)(high & mask1);
1390                 ret = (deUint32)((data1 << len0) | data0);
1391         }
1392
1393         if (reverse)
1394         {
1395                 const deUint32 len = last - first + 1;
1396                 const deUint32 orig = ret;
1397                 ret = 0;
1398
1399                 for (deUint32 i = 0; i < len; i++)
1400                 {
1401                         ret |= ((orig >> (len - 1 - i)) & 1) << i;
1402                 }
1403         }
1404
1405         return ret;
1406 }
1407
1408 inline deInt32 signExtend (deInt32 value, deInt32 srcBits, deInt32 dstBits)
1409 {
1410         deUint32 sign = value & (1 << (srcBits - 1));
1411
1412         if (!sign) return value;
1413
1414         deInt32 dstMask = (deInt32)(((deUint64)1 << dstBits) - 1);
1415         deInt32 extendedBits = 0xffffffff << srcBits;
1416         return (value | extendedBits) & dstMask;
1417 }
1418
1419 inline deInt32 unquantize (deInt32 x, int mode, bool hasSign)
1420 {
1421         if (hasSign)
1422         {
1423            bool s = false;
1424
1425            if (epBits[mode] >= 16) return x;
1426
1427            if (x < 0)
1428            {
1429                    s = true;
1430                    x = -x;
1431            }
1432
1433            if (x == 0)
1434                    x = 0;
1435            else if (x >= (((deInt32)1 << (epBits[mode] - 1)) - 1))
1436                    x = 0x7fff;
1437            else
1438                    x = (((deInt32)x << 15) + 0x4000) >> (epBits[mode] - 1);
1439
1440            if (s)
1441                    x = -x;
1442
1443            return x;
1444         }
1445         else
1446         {
1447            if (epBits[mode] >= 15)
1448                    return x;
1449            else if (x == 0)
1450                    return 0;
1451            else if (x == (((deInt32)1 << epBits[mode]) - 1))
1452                    return 0xffff;
1453            else
1454                    return ((((deInt32)x << 15) + 0x4000) >> (epBits[mode] - 1));
1455         }
1456 }
1457
1458 inline deInt32 interpolate (deInt32 a, deInt32 b, deUint32 index, deUint32 indexPrecision)
1459 {
1460         const deUint16* weights[]       = {weights2, weights3, weights4};
1461         const deUint16* weight          = weights[indexPrecision-2];
1462         DE_ASSERT(indexPrecision >= 2 && indexPrecision <= 4);
1463
1464         return (((64 - weight[index]) * a + weight[index] * b + 32) >> 6);
1465 }
1466
1467 inline deInt16 finishUnquantize (deInt32 x, bool hasSign)
1468 {
1469         if (hasSign)
1470         {
1471                 if (x < 0)
1472                         x = -(((-x) * 31) >> 5);
1473                 else
1474                         x = (x * 31) >> 5;
1475
1476                 if (x < 0)
1477                         x = (-x) | 0x8000;
1478         }
1479         else
1480         {
1481                 x = (x * 31) / 64;
1482         }
1483
1484         return (deInt16)x;
1485 }
1486
1487 } // BcDecompressInternal
1488
1489 void decompressBc1 (const PixelBufferAccess& dst, const deUint8* src, bool hasAlpha)
1490 {
1491         using namespace BcDecompressInternal;
1492
1493         deUint8* const                  dstPtr                  = (deUint8*)dst.getDataPtr();
1494         const deUint32                  dstRowPitch             = dst.getRowPitch();
1495         const deUint32                  dstPixelSize    = 4;
1496         const deUint16                  color0_16               = ((deUint16*)src)[0];
1497         const deUint16                  color1_16               = ((deUint16*)src)[1];
1498         const deUint32                  color0                  = bgr16torgba32(color0_16);
1499         const deUint32                  color1                  = bgr16torgba32(color1_16);
1500         const deUint8* const    indices8                = &src[4];
1501
1502         const bool                              alphaMode               = color1_16 > color0_16;
1503
1504         const deInt32                   indices[16]             =
1505         {
1506                 (indices8[0] >> 0) & 0x3,
1507                 (indices8[0] >> 2) & 0x3,
1508                 (indices8[0] >> 4) & 0x3,
1509                 (indices8[0] >> 6) & 0x3,
1510                 (indices8[1] >> 0) & 0x3,
1511                 (indices8[1] >> 2) & 0x3,
1512                 (indices8[1] >> 4) & 0x3,
1513                 (indices8[1] >> 6) & 0x3,
1514                 (indices8[2] >> 0) & 0x3,
1515                 (indices8[2] >> 2) & 0x3,
1516                 (indices8[2] >> 4) & 0x3,
1517                 (indices8[2] >> 6) & 0x3,
1518                 (indices8[3] >> 0) & 0x3,
1519                 (indices8[3] >> 2) & 0x3,
1520                 (indices8[3] >> 4) & 0x3,
1521                 (indices8[3] >> 6) & 0x3
1522         };
1523
1524         const deUint32                  colors[4]               =
1525         {
1526                 color0,
1527                 color1,
1528                 alphaMode ? averageColor(color0, color1) : interpolateColor(color1, color0),
1529                 alphaMode ? (hasAlpha ? 0 : 0xff000000) : interpolateColor(color0, color1)
1530         };
1531
1532         for (deUint32 y = 0; y < (deUint32)BC_BLOCK_HEIGHT; y++)
1533         {
1534                 for (deUint32 x = 0; x < (deUint32)BC_BLOCK_WIDTH; x++)
1535                 {
1536                         deUint32* const dstPixel = (deUint32*)(dstPtr + y * dstRowPitch + x * dstPixelSize);
1537                         *dstPixel = colors[indices[y * BC_BLOCK_WIDTH + x]];
1538                 }
1539         }
1540 }
1541
1542 void decompressBc2 (const PixelBufferAccess& dst, const deUint8* src)
1543 {
1544         using namespace BcDecompressInternal;
1545
1546         deUint8* const                  dstPtr                  = (deUint8*)dst.getDataPtr();
1547         const deUint32                  dstRowPitch             = dst.getRowPitch();
1548         const deUint32                  dstPixelSize    = 4;
1549         const deUint16                  color0_16               = ((deUint16*)src)[4];
1550         const deUint16                  color1_16               = ((deUint16*)src)[5];
1551         const deUint32                  color0                  = bgr16torgba32(color0_16);
1552         const deUint32                  color1                  = bgr16torgba32(color1_16);
1553         const deUint8* const    indices8                = &src[12];
1554         const deUint8* const    alphas8                 = src;
1555
1556         const deInt32                   indices[16]             =
1557         {
1558                 (indices8[0] >> 0) & 0x3,
1559                 (indices8[0] >> 2) & 0x3,
1560                 (indices8[0] >> 4) & 0x3,
1561                 (indices8[0] >> 6) & 0x3,
1562                 (indices8[1] >> 0) & 0x3,
1563                 (indices8[1] >> 2) & 0x3,
1564                 (indices8[1] >> 4) & 0x3,
1565                 (indices8[1] >> 6) & 0x3,
1566                 (indices8[2] >> 0) & 0x3,
1567                 (indices8[2] >> 2) & 0x3,
1568                 (indices8[2] >> 4) & 0x3,
1569                 (indices8[2] >> 6) & 0x3,
1570                 (indices8[3] >> 0) & 0x3,
1571                 (indices8[3] >> 2) & 0x3,
1572                 (indices8[3] >> 4) & 0x3,
1573                 (indices8[3] >> 6) & 0x3
1574         };
1575
1576         const deInt32                   alphas[16]              =
1577         {
1578                 extend4To8(((alphas8[0] >> 0) & 0xf)) << 24,
1579                 extend4To8(((alphas8[0] >> 4) & 0xf)) << 24,
1580                 extend4To8(((alphas8[1] >> 0) & 0xf)) << 24,
1581                 extend4To8(((alphas8[1] >> 4) & 0xf)) << 24,
1582                 extend4To8(((alphas8[2] >> 0) & 0xf)) << 24,
1583                 extend4To8(((alphas8[2] >> 4) & 0xf)) << 24,
1584                 extend4To8(((alphas8[3] >> 0) & 0xf)) << 24,
1585                 extend4To8(((alphas8[3] >> 4) & 0xf)) << 24,
1586                 extend4To8(((alphas8[4] >> 0) & 0xf)) << 24,
1587                 extend4To8(((alphas8[4] >> 4) & 0xf)) << 24,
1588                 extend4To8(((alphas8[5] >> 0) & 0xf)) << 24,
1589                 extend4To8(((alphas8[5] >> 4) & 0xf)) << 24,
1590                 extend4To8(((alphas8[6] >> 0) & 0xf)) << 24,
1591                 extend4To8(((alphas8[6] >> 4) & 0xf)) << 24,
1592                 extend4To8(((alphas8[7] >> 0) & 0xf)) << 24,
1593                 extend4To8(((alphas8[7] >> 4) & 0xf)) << 24
1594         };
1595
1596         const deUint32                  colors[4]               =
1597         {
1598                 color0,
1599                 color1,
1600                 interpolateColor(color1, color0),
1601                 interpolateColor(color0, color1)
1602         };
1603
1604         for (deUint32 y = 0; y < (deUint32)BC_BLOCK_HEIGHT; y++)
1605         {
1606                 for (deUint32 x = 0; x < (deUint32)BC_BLOCK_WIDTH; x++)
1607                 {
1608                         deUint32* const dstPixel = (deUint32*)(dstPtr + y * dstRowPitch + x * dstPixelSize);
1609                         *dstPixel = (colors[indices[y * BC_BLOCK_WIDTH + x]] & 0x00ffffff) | alphas[y * BC_BLOCK_WIDTH + x];
1610                 }
1611         }
1612 }
1613
1614 void decompressBc3 (const PixelBufferAccess& dst, const deUint8* src)
1615 {
1616         using namespace BcDecompressInternal;
1617
1618         deUint8* const                  dstPtr                          = (deUint8*)dst.getDataPtr();
1619         const deUint32                  dstRowPitch                     = dst.getRowPitch();
1620         const deUint32                  dstPixelSize            = 4;
1621         const deUint8                   alpha0                          = src[0];
1622         const deUint8                   alpha1                          = src[1];
1623         const deUint16                  color0_16                       = ((deUint16*)src)[4];
1624         const deUint16                  color1_16                       = ((deUint16*)src)[5];
1625         const deUint32                  color0                          = bgr16torgba32(color0_16);
1626         const deUint32                  color1                          = bgr16torgba32(color1_16);
1627         const deUint8* const    indices8                        = &src[12];
1628         const deUint64                  alphaBits                       = get64BitBlockLE(src, 0) >> 16;
1629         deUint32                                alphas[8];
1630
1631         const deInt32                   indices[16]                     =
1632         {
1633                 (indices8[0] >> 0) & 0x3,
1634                 (indices8[0] >> 2) & 0x3,
1635                 (indices8[0] >> 4) & 0x3,
1636                 (indices8[0] >> 6) & 0x3,
1637                 (indices8[1] >> 0) & 0x3,
1638                 (indices8[1] >> 2) & 0x3,
1639                 (indices8[1] >> 4) & 0x3,
1640                 (indices8[1] >> 6) & 0x3,
1641                 (indices8[2] >> 0) & 0x3,
1642                 (indices8[2] >> 2) & 0x3,
1643                 (indices8[2] >> 4) & 0x3,
1644                 (indices8[2] >> 6) & 0x3,
1645                 (indices8[3] >> 0) & 0x3,
1646                 (indices8[3] >> 2) & 0x3,
1647                 (indices8[3] >> 4) & 0x3,
1648                 (indices8[3] >> 6) & 0x3
1649         };
1650
1651         const deInt32                   alphaIndices[16]        =
1652         {
1653                 (deInt32)((alphaBits >> 0) & 0x7),
1654                 (deInt32)((alphaBits >> 3) & 0x7),
1655                 (deInt32)((alphaBits >> 6) & 0x7),
1656                 (deInt32)((alphaBits >> 9) & 0x7),
1657                 (deInt32)((alphaBits >> 12) & 0x7),
1658                 (deInt32)((alphaBits >> 15) & 0x7),
1659                 (deInt32)((alphaBits >> 18) & 0x7),
1660                 (deInt32)((alphaBits >> 21) & 0x7),
1661                 (deInt32)((alphaBits >> 24) & 0x7),
1662                 (deInt32)((alphaBits >> 27) & 0x7),
1663                 (deInt32)((alphaBits >> 30) & 0x7),
1664                 (deInt32)((alphaBits >> 33) & 0x7),
1665                 (deInt32)((alphaBits >> 36) & 0x7),
1666                 (deInt32)((alphaBits >> 39) & 0x7),
1667                 (deInt32)((alphaBits >> 42) & 0x7),
1668                 (deInt32)((alphaBits >> 45) & 0x7)
1669         };
1670
1671         const deUint32                  colors[4]                       =
1672         {
1673                 color0,
1674                 color1,
1675                 interpolateColor(color1, color0),
1676                 interpolateColor(color0, color1)
1677         };
1678
1679         alphas[0] = alpha0 << 24;
1680         alphas[1] = alpha1 << 24;
1681
1682         if (alpha0 > alpha1)
1683         {
1684                 for (deUint32 i = 0; i < 6; i++)
1685                         alphas[i + 2] = (((deUint32)alpha0 * (6 - i) + (deUint32)alpha1 * (1 + i)) / 7) << 24;
1686         }
1687         else
1688         {
1689                 for (deUint32 i = 0; i < 4; i++)
1690                         alphas[i + 2] = (((deUint32)alpha0 * (4 - i) + (deUint32)alpha1 * (1 + i)) / 5) << 24;
1691                 alphas[6] = 0;
1692                 alphas[7] = 0xff000000;
1693         }
1694
1695         for (deUint32 y = 0; y < (deUint32)BC_BLOCK_HEIGHT; y++)
1696         {
1697                 for (deUint32 x = 0; x < (deUint32)BC_BLOCK_WIDTH; x++)
1698                 {
1699                         deUint32* const dstPixel = (deUint32*)(dstPtr + y * dstRowPitch + x * dstPixelSize);
1700                         *dstPixel = (colors[indices[y * BC_BLOCK_WIDTH + x]] & 0x00ffffff) | alphas[alphaIndices[y * BC_BLOCK_WIDTH + x]];
1701                 }
1702         }
1703 }
1704
1705 void decompressBc4 (const PixelBufferAccess& dst, const deUint8* src, bool hasSign)
1706 {
1707         using namespace BcDecompressInternal;
1708
1709         deUint8* const                  dstPtr                  = (deUint8*)dst.getDataPtr();
1710         const deUint32                  dstRowPitch             = dst.getRowPitch();
1711         const deUint32                  dstPixelSize    = 4;
1712         const deUint8                   red0                    = src[0];
1713         const deUint8                   red1                    = src[1];
1714         const deInt8                    red0s                   = ((deInt8*)src)[0];
1715         const deInt8                    red1s                   = ((deInt8*)src)[1];
1716         const deUint64                  indexBits               = get64BitBlockLE(src, 0) >> 16;
1717         float                                   reds[8];
1718
1719         const deInt32                   indices[16]             =
1720         {
1721                 (deInt32)((indexBits >> 0) & 0x7),
1722                 (deInt32)((indexBits >> 3) & 0x7),
1723                 (deInt32)((indexBits >> 6) & 0x7),
1724                 (deInt32)((indexBits >> 9) & 0x7),
1725                 (deInt32)((indexBits >> 12) & 0x7),
1726                 (deInt32)((indexBits >> 15) & 0x7),
1727                 (deInt32)((indexBits >> 18) & 0x7),
1728                 (deInt32)((indexBits >> 21) & 0x7),
1729                 (deInt32)((indexBits >> 24) & 0x7),
1730                 (deInt32)((indexBits >> 27) & 0x7),
1731                 (deInt32)((indexBits >> 30) & 0x7),
1732                 (deInt32)((indexBits >> 33) & 0x7),
1733                 (deInt32)((indexBits >> 36) & 0x7),
1734                 (deInt32)((indexBits >> 39) & 0x7),
1735                 (deInt32)((indexBits >> 42) & 0x7),
1736                 (deInt32)((indexBits >> 45) & 0x7)
1737         };
1738
1739         reds[0] = hasSign ? int8ToFloat(red0s) : uint8ToFloat(red0);
1740         reds[1] = hasSign ? int8ToFloat(red1s) : uint8ToFloat(red1);
1741
1742         if (reds[0] > reds[1])
1743         {
1744                 for (deUint32 i = 0; i < 6; i++)
1745                         reds[i + 2] = (reds[0] * (6.0f - (float)i) + reds[1] * (1.0f + (float)i)) / 7.0f;
1746         }
1747         else
1748         {
1749                 for (deUint32 i = 0; i < 4; i++)
1750                         reds[i + 2] = (reds[0] * (4.0f - (float)i) + reds[1] * (1.0f + (float)i)) / 5.0f;
1751                 reds[6] = hasSign ? -1.0f : 0.0f;
1752                 reds[7] = 1.0f;
1753         }
1754
1755         for (deUint32 y = 0; y < (deUint32)BC_BLOCK_HEIGHT; y++)
1756         {
1757                 for (deUint32 x = 0; x < (deUint32)BC_BLOCK_WIDTH; x++)
1758                 {
1759                         float* const dstPixel = (float*)(dstPtr + y * dstRowPitch + x * dstPixelSize);
1760                         *dstPixel = reds[indices[y * BC_BLOCK_WIDTH + x]];
1761                 }
1762         }
1763 }
1764
1765 void decompressBc5 (const PixelBufferAccess& dst, const deUint8* src, bool hasSign)
1766 {
1767         using namespace BcDecompressInternal;
1768
1769         deUint8* const                  dstPtr                  = (deUint8*)dst.getDataPtr();
1770         const deUint32                  dstRowPitch             = dst.getRowPitch();
1771         const deUint32                  dstPixelSize    = 8;
1772         float                                   rg[2][8];
1773         deUint32                                indices[2][16];
1774
1775         for (deUint32 c = 0; c < 2; c++)
1776         {
1777                 const deUint32                  offset                  = c * 8;
1778                 const deUint8                   rg0                             = src[offset];
1779                 const deUint8                   rg1                             = src[offset + 1];
1780                 const deInt8                    rg0s                    = ((deInt8*)src)[offset];
1781                 const deInt8                    rg1s                    = ((deInt8*)src)[offset + 1];
1782                 const deUint64                  indexBits               = get64BitBlockLE(src, c) >> 16;
1783
1784                 for (deUint32 i = 0; i < 16; i++)
1785                         indices[c][i] = (indexBits >> (i * 3)) & 0x7;
1786
1787                 rg[c][0] = hasSign ? int8ToFloat(rg0s) : uint8ToFloat(rg0);
1788                 rg[c][1] = hasSign ? int8ToFloat(rg1s) : uint8ToFloat(rg1);
1789
1790                 if (rg[c][0] > rg[c][1])
1791                 {
1792                         for (deUint32 i = 0; i < 6; i++)
1793                                 rg[c][i + 2] = (rg[c][0] * (6.0f - (float)i) + rg[c][1] * (1.0f + (float)i)) / 7.0f;
1794                 }
1795                 else
1796                 {
1797                         for (deUint32 i = 0; i < 4; i++)
1798                                 rg[c][i + 2] = (rg[c][0] * (4.0f - (float)i) + rg[c][1] * (1.0f + (float)i)) / 5.0f;
1799                         rg[c][6] = hasSign ? -1.0f : 0.0f;
1800                         rg[c][7] = 1.0f;
1801                 }
1802         }
1803
1804         for (deUint32 y = 0; y < (deUint32)BC_BLOCK_HEIGHT; y++)
1805         {
1806                 for (deUint32 x = 0; x < (deUint32)BC_BLOCK_WIDTH; x++)
1807                 {
1808                         float* const dstPixel = (float*)(dstPtr + y * dstRowPitch + x * dstPixelSize);
1809                         for (deUint32 i = 0; i < 2; i++)
1810                                 dstPixel[i] = rg[i][indices[i][y * BC_BLOCK_WIDTH + x]];
1811                 }
1812         }
1813 }
1814
1815 void decompressBc6H (const PixelBufferAccess& dst, const deUint8* src, bool hasSign)
1816 {
1817         using namespace BcDecompressInternal;
1818
1819         deUint8* const                  dstPtr                  = (deUint8*)dst.getDataPtr();
1820         const deUint32                  dstRowPitch             = dst.getRowPitch();
1821         const deUint32                  dstPixelSize    = 6;
1822
1823         deInt32                                 mode                    = extractModeBc6(src[0]);
1824         IVec4                                   r                               (0);
1825         IVec4                                   g                               (0);
1826         IVec4                                   b                               (0);
1827         deUint32                                deltaBitsR              = 0;
1828         deUint32                                deltaBitsG              = 0;
1829         deUint32                                deltaBitsB              = 0;
1830         const deUint64                  low                             = ((deUint64*)src)[0];
1831         const deUint64                  high                    = ((deUint64*)src)[1];
1832         const deUint32                  d                               = mode < 10 ? getBits128(low, high, 77, 81) : 0;
1833         const deUint32                  numRegions              = mode > 9 ? 1 : 2;
1834         const deUint32                  numEndpoints    = numRegions * 2;
1835         const bool                              transformed             = mode != 9 && mode != 10;
1836         const deUint32                  colorIndexBC    = mode < 10 ? 3 : 4;
1837         deUint64                                colorIndexData  = high >> (mode < 10 ? 18 : 1);
1838         const deUint32                  anchorIndex[2]  = { 0, anchorIndicesSecondSubset2[d] };
1839
1840         switch (mode)
1841         {
1842                 case 0:
1843                         g[2] |= getBits128(low, high, 2, 2) << 4;
1844                         b[2] |= getBits128(low, high, 3, 3) << 4;
1845                         b[3] |= getBits128(low, high, 4, 4) << 4;
1846                         r[0] |= getBits128(low, high, 5, 14);
1847                         g[0] |= getBits128(low, high, 15, 24);
1848                         b[0] |= getBits128(low, high, 25, 34);
1849                         r[1] |= getBits128(low, high, 35, 39);
1850                         g[3] |= getBits128(low, high, 40, 40) << 4;
1851                         g[2] |= getBits128(low, high, 41, 44);
1852                         g[1] |= getBits128(low, high, 45, 49);
1853                         b[3] |= getBits128(low, high, 50, 50);
1854                         g[3] |= getBits128(low, high, 51, 54);
1855                         b[1] |= getBits128(low, high, 55, 59);
1856                         b[3] |= getBits128(low, high, 60, 60) << 1;
1857                         b[2] |= getBits128(low, high, 61, 64);
1858                         r[2] |= getBits128(low, high, 65, 69);
1859                         b[3] |= getBits128(low, high, 70, 70) << 2;
1860                         r[3] |= getBits128(low, high, 71, 75);
1861                         b[3] |= getBits128(low, high, 76, 76) << 3;
1862                         deltaBitsR = deltaBitsG = deltaBitsB = 5;
1863                         break;
1864
1865                 case 1:
1866                         g[2] |= getBits128(low, high, 2, 2) << 5;
1867                         g[3] |= getBits128(low, high, 3, 3) << 4;
1868                         g[3] |= getBits128(low, high, 4, 4) << 5;
1869                         r[0] |= getBits128(low, high, 5, 11);
1870                         b[3] |= getBits128(low, high, 12, 12);
1871                         b[3] |= getBits128(low, high, 13, 13) << 1;
1872                         b[2] |= getBits128(low, high, 14, 14) << 4;
1873                         g[0] |= getBits128(low, high, 15, 21);
1874                         b[2] |= getBits128(low, high, 22, 22) << 5;
1875                         b[3] |= getBits128(low, high, 23, 23) << 2;
1876                         g[2] |= getBits128(low, high, 24, 24) << 4;
1877                         b[0] |= getBits128(low, high, 25, 31);
1878                         b[3] |= getBits128(low, high, 32, 32) << 3;
1879                         b[3] |= getBits128(low, high, 33, 33) << 5;
1880                         b[3] |= getBits128(low, high, 34, 34) << 4;
1881                         r[1] |= getBits128(low, high, 35, 40);
1882                         g[2] |= getBits128(low, high, 41, 44);
1883                         g[1] |= getBits128(low, high, 45, 50);
1884                         g[3] |= getBits128(low, high, 51, 54);
1885                         b[1] |= getBits128(low, high, 55, 60);
1886                         b[2] |= getBits128(low, high, 61, 64);
1887                         r[2] |= getBits128(low, high, 65, 70);
1888                         r[3] |= getBits128(low, high, 71, 76);
1889                         deltaBitsR = deltaBitsG = deltaBitsB = 6;
1890                         break;
1891
1892                 case 2:
1893                         r[0] |= getBits128(low, high, 5, 14);
1894                         g[0] |= getBits128(low, high, 15, 24);
1895                         b[0] |= getBits128(low, high, 25, 34);
1896                         r[1] |= getBits128(low, high, 35, 39);
1897                         r[0] |= getBits128(low, high, 40, 40) << 10;
1898                         g[2] |= getBits128(low, high, 41, 44);
1899                         g[1] |= getBits128(low, high, 45, 48);
1900                         g[0] |= getBits128(low, high, 49, 49) << 10;
1901                         b[3] |= getBits128(low, high, 50, 50);
1902                         g[3] |= getBits128(low, high, 51, 54);
1903                         b[1] |= getBits128(low, high, 55, 58);
1904                         b[0] |= getBits128(low, high, 59, 59) << 10;
1905                         b[3] |= getBits128(low, high, 60, 60) << 1;
1906                         b[2] |= getBits128(low, high, 61, 64);
1907                         r[2] |= getBits128(low, high, 65, 69);
1908                         b[3] |= getBits128(low, high, 70, 70) << 2;
1909                         r[3] |= getBits128(low, high, 71, 75);
1910                         b[3] |= getBits128(low, high, 76, 76) << 3;
1911                         deltaBitsR = 5;
1912                         deltaBitsG = deltaBitsB = 4;
1913                         break;
1914
1915                 case 3:
1916                         r[0] |= getBits128(low, high, 5, 14);
1917                         g[0] |= getBits128(low, high, 15, 24);
1918                         b[0] |= getBits128(low, high, 25, 34);
1919                         r[1] |= getBits128(low, high, 35, 38);
1920                         r[0] |= getBits128(low, high, 39, 39) << 10;
1921                         g[3] |= getBits128(low, high, 40, 40) << 4;
1922                         g[2] |= getBits128(low, high, 41, 44);
1923                         g[1] |= getBits128(low, high, 45, 49);
1924                         g[0] |= getBits128(low, high, 50, 50) << 10;
1925                         g[3] |= getBits128(low, high, 51, 54);
1926                         b[1] |= getBits128(low, high, 55, 58);
1927                         b[0] |= getBits128(low, high, 59, 59) << 10;
1928                         b[3] |= getBits128(low, high, 60, 60) << 1;
1929                         b[2] |= getBits128(low, high, 61, 64);
1930                         r[2] |= getBits128(low, high, 65, 68);
1931                         b[3] |= getBits128(low, high, 69, 69);
1932                         b[3] |= getBits128(low, high, 70, 70) << 2;
1933                         r[3] |= getBits128(low, high, 71, 74);
1934                         g[2] |= getBits128(low, high, 75, 75) << 4;
1935                         b[3] |= getBits128(low, high, 76, 76) << 3;
1936                         deltaBitsR = deltaBitsB = 4;
1937                         deltaBitsG = 5;
1938                         break;
1939
1940                 case 4:
1941                         r[0] |= getBits128(low, high, 5, 14);
1942                         g[0] |= getBits128(low, high, 15, 24);
1943                         b[0] |= getBits128(low, high, 25, 34);
1944                         r[1] |= getBits128(low, high, 35, 38);
1945                         r[0] |= getBits128(low, high, 39, 39) << 10;
1946                         b[2] |= getBits128(low, high, 40, 40) << 4;
1947                         g[2] |= getBits128(low, high, 41, 44);
1948                         g[1] |= getBits128(low, high, 45, 48);
1949                         g[0] |= getBits128(low, high, 49, 49) << 10;
1950                         b[3] |= getBits128(low, high, 50, 50);
1951                         g[3] |= getBits128(low, high, 51, 54);
1952                         b[1] |= getBits128(low, high, 55, 59);
1953                         b[0] |= getBits128(low, high, 60, 60) << 10;
1954                         b[2] |= getBits128(low, high, 61, 64);
1955                         r[2] |= getBits128(low, high, 65, 68);
1956                         b[3] |= getBits128(low, high, 69, 69) << 1;
1957                         b[3] |= getBits128(low, high, 70, 70) << 2;
1958                         r[3] |= getBits128(low, high, 71, 74);
1959                         b[3] |= getBits128(low, high, 75, 75) << 4;
1960                         b[3] |= getBits128(low, high, 76, 76) << 3;
1961                         deltaBitsR = deltaBitsG = 4;
1962                         deltaBitsB = 5;
1963                         break;
1964
1965                 case 5:
1966                         r[0] |= getBits128(low, high, 5, 13);
1967                         b[2] |= getBits128(low, high, 14, 14) << 4;
1968                         g[0] |= getBits128(low, high, 15, 23);
1969                         g[2] |= getBits128(low, high, 24, 24) << 4;
1970                         b[0] |= getBits128(low, high, 25, 33);
1971                         b[3] |= getBits128(low, high, 34, 34) << 4;
1972                         r[1] |= getBits128(low, high, 35, 39);
1973                         g[3] |= getBits128(low, high, 40, 40) << 4;
1974                         g[2] |= getBits128(low, high, 41, 44);
1975                         g[1] |= getBits128(low, high, 45, 49);
1976                         b[3] |= getBits128(low, high, 50, 50);
1977                         g[3] |= getBits128(low, high, 51, 54);
1978                         b[1] |= getBits128(low, high, 55, 59);
1979                         b[3] |= getBits128(low, high, 60, 60) << 1;
1980                         b[2] |= getBits128(low, high, 61, 64);
1981                         r[2] |= getBits128(low, high, 65, 69);
1982                         b[3] |= getBits128(low, high, 70, 70) << 2;
1983                         r[3] |= getBits128(low, high, 71, 75);
1984                         b[3] |= getBits128(low, high, 76, 76) << 3;
1985                         deltaBitsR = deltaBitsG = deltaBitsB = 5;
1986                         break;
1987
1988                 case 6:
1989                         r[0] |= getBits128(low, high, 5, 12);
1990                         g[3] |= getBits128(low, high, 13, 13) << 4;
1991                         b[2] |= getBits128(low, high, 14, 14) << 4;
1992                         g[0] |= getBits128(low, high, 15, 22);
1993                         b[3] |= getBits128(low, high, 23, 23) << 2;
1994                         g[2] |= getBits128(low, high, 24, 24) << 4;
1995                         b[0] |= getBits128(low, high, 25, 32);
1996                         b[3] |= getBits128(low, high, 33, 33) << 3;
1997                         b[3] |= getBits128(low, high, 34, 34) << 4;
1998                         r[1] |= getBits128(low, high, 35, 40);
1999                         g[2] |= getBits128(low, high, 41, 44);
2000                         g[1] |= getBits128(low, high, 45, 49);
2001                         b[3] |= getBits128(low, high, 50, 50);
2002                         g[3] |= getBits128(low, high, 51, 54);
2003                         b[1] |= getBits128(low, high, 55, 59);
2004                         b[3] |= getBits128(low, high, 60, 60) << 1;
2005                         b[2] |= getBits128(low, high, 61, 64);
2006                         r[2] |= getBits128(low, high, 65, 70);
2007                         r[3] |= getBits128(low, high, 71, 76);
2008                         deltaBitsR = 6;
2009                         deltaBitsG = deltaBitsB = 5;
2010                         break;
2011
2012                 case 7:
2013                         r[0] |= getBits128(low, high, 5, 12);
2014                         b[3] |= getBits128(low, high, 13, 13);
2015                         b[2] |= getBits128(low, high, 14, 14) << 4;
2016                         g[0] |= getBits128(low, high, 15, 22);
2017                         g[2] |= getBits128(low, high, 23, 23) << 5;
2018                         g[2] |= getBits128(low, high, 24, 24) << 4;
2019                         b[0] |= getBits128(low, high, 25, 32);
2020                         g[3] |= getBits128(low, high, 33, 33) << 5;
2021                         b[3] |= getBits128(low, high, 34, 34) << 4;
2022                         r[1] |= getBits128(low, high, 35, 39);
2023                         g[3] |= getBits128(low, high, 40, 40) << 4;
2024                         g[2] |= getBits128(low, high, 41, 44);
2025                         g[1] |= getBits128(low, high, 45, 50);
2026                         g[3] |= getBits128(low, high, 51, 54);
2027                         b[1] |= getBits128(low, high, 55, 59);
2028                         b[3] |= getBits128(low, high, 60, 60) << 1;
2029                         b[2] |= getBits128(low, high, 61, 64);
2030                         r[2] |= getBits128(low, high, 65, 69);
2031                         b[3] |= getBits128(low, high, 70, 70) << 2;
2032                         r[3] |= getBits128(low, high, 71, 75);
2033                         b[3] |= getBits128(low, high, 76, 76) << 3;
2034                         deltaBitsR = deltaBitsB = 5;
2035                         deltaBitsG = 6;
2036                         break;
2037
2038                 case 8:
2039                         r[0] |= getBits128(low, high, 5, 12);
2040                         b[3] |= getBits128(low, high, 13, 13) << 1;
2041                         b[2] |= getBits128(low, high, 14, 14) << 4;
2042                         g[0] |= getBits128(low, high, 15, 22);
2043                         b[2] |= getBits128(low, high, 23, 23) << 5;
2044                         g[2] |= getBits128(low, high, 24, 24) << 4;
2045                         b[0] |= getBits128(low, high, 25, 32);
2046                         b[3] |= getBits128(low, high, 33, 33) << 5;
2047                         b[3] |= getBits128(low, high, 34, 34) << 4;
2048                         r[1] |= getBits128(low, high, 35, 39);
2049                         g[3] |= getBits128(low, high, 40, 40) << 4;
2050                         g[2] |= getBits128(low, high, 41, 44);
2051                         g[1] |= getBits128(low, high, 45, 49);
2052                         b[3] |= getBits128(low, high, 50, 50);
2053                         g[3] |= getBits128(low, high, 51, 54);
2054                         b[1] |= getBits128(low, high, 55, 60);
2055                         b[2] |= getBits128(low, high, 61, 64);
2056                         r[2] |= getBits128(low, high, 65, 69);
2057                         b[3] |= getBits128(low, high, 70, 70) << 2;
2058                         r[3] |= getBits128(low, high, 71, 75);
2059                         b[3] |= getBits128(low, high, 76, 76) << 3;
2060                         deltaBitsR = deltaBitsG = 5;
2061                         deltaBitsB = 6;
2062                         break;
2063
2064                 case 9:
2065                         r[0] |= getBits128(low, high, 5, 10);
2066                         g[3] |= getBits128(low, high, 11, 11) << 4;
2067                         b[3] |= getBits128(low, high, 12, 13);
2068                         b[2] |= getBits128(low, high, 14, 14) << 4;
2069                         g[0] |= getBits128(low, high, 15, 20);
2070                         g[2] |= getBits128(low, high, 21, 21) << 5;
2071                         b[2] |= getBits128(low, high, 22, 22) << 5;
2072                         b[3] |= getBits128(low, high, 23, 23) << 2;
2073                         g[2] |= getBits128(low, high, 24, 24) << 4;
2074                         b[0] |= getBits128(low, high, 25, 30);
2075                         g[3] |= getBits128(low, high, 31, 31) << 5;
2076                         b[3] |= getBits128(low, high, 32, 32) << 3;
2077                         b[3] |= getBits128(low, high, 33, 33) << 5;
2078                         b[3] |= getBits128(low, high, 34, 34) << 4;
2079                         r[1] |= getBits128(low, high, 35, 40);
2080                         g[2] |= getBits128(low, high, 41, 44);
2081                         g[1] |= getBits128(low, high, 45, 50);
2082                         g[3] |= getBits128(low, high, 51, 54);
2083                         b[1] |= getBits128(low, high, 55, 60);
2084                         b[2] |= getBits128(low, high, 61, 64);
2085                         r[2] |= getBits128(low, high, 65, 70);
2086                         r[3] |= getBits128(low, high, 71, 76);
2087                         deltaBitsR = deltaBitsG = deltaBitsB = 6;
2088                         break;
2089
2090                 case 10:
2091                         r[0] |= getBits128(low, high, 5, 14);
2092                         g[0] |= getBits128(low, high, 15, 24);
2093                         b[0] |= getBits128(low, high, 25, 34);
2094                         r[1] |= getBits128(low, high, 35, 44);
2095                         g[1] |= getBits128(low, high, 45, 54);
2096                         b[1] |= getBits128(low, high, 55, 64);
2097                         deltaBitsR = deltaBitsG = deltaBitsB = 10;
2098                         break;
2099
2100                 case 11:
2101                         r[0] |= getBits128(low, high, 5, 14);
2102                         g[0] |= getBits128(low, high, 15, 24);
2103                         b[0] |= getBits128(low, high, 25, 34);
2104                         r[1] |= getBits128(low, high, 35, 43);
2105                         r[0] |= getBits128(low, high, 44, 44) << 10;
2106                         g[1] |= getBits128(low, high, 45, 53);
2107                         g[0] |= getBits128(low, high, 54, 54) << 10;
2108                         b[1] |= getBits128(low, high, 55, 63);
2109                         b[0] |= getBits128(low, high, 64, 64) << 10;
2110                         deltaBitsR = deltaBitsG = deltaBitsB = 9;
2111                         break;
2112
2113                 case 12:
2114                         r[0] |= getBits128(low, high, 5, 14);
2115                         g[0] |= getBits128(low, high, 15, 24);
2116                         b[0] |= getBits128(low, high, 25, 34);
2117                         r[1] |= getBits128(low, high, 35, 42);
2118                         r[0] |= getBits128(low, high, 44, 43) << 10;
2119                         g[1] |= getBits128(low, high, 45, 52);
2120                         g[0] |= getBits128(low, high, 54, 53) << 10;
2121                         b[1] |= getBits128(low, high, 55, 62);
2122                         b[0] |= getBits128(low, high, 64, 63) << 10;
2123                         deltaBitsR = deltaBitsG = deltaBitsB = 8;
2124                         break;
2125
2126                 case 13:
2127                         r[0] |= getBits128(low, high, 5, 14);
2128                         g[0] |= getBits128(low, high, 15, 24);
2129                         b[0] |= getBits128(low, high, 25, 34);
2130                         r[1] |= getBits128(low, high, 35, 38);
2131                         r[0] |= getBits128(low, high, 44, 39) << 10;
2132                         g[1] |= getBits128(low, high, 45, 48);
2133                         g[0] |= getBits128(low, high, 54, 49) << 10;
2134                         b[1] |= getBits128(low, high, 55, 58);
2135                         b[0] |= getBits128(low, high, 64, 59) << 10;
2136                         deltaBitsR = deltaBitsG = deltaBitsB = 4;
2137                         break;
2138         };
2139
2140         if (hasSign)
2141         {
2142                 r[0] = signExtend(r[0], epBits[mode], 32);
2143                 g[0] = signExtend(g[0], epBits[mode], 32);
2144                 b[0] = signExtend(b[0], epBits[mode], 32);
2145         }
2146
2147         if (transformed)
2148         {
2149                 for (deUint32 i = 1; i < numEndpoints; i++)
2150                 {
2151                         r[i] = signExtend(r[i], deltaBitsR, 32);
2152                         r[i] = (r[0] + r[i]) & (((deUint32)1 << epBits[mode]) - 1);
2153                         g[i] = signExtend(g[i], deltaBitsG, 32);
2154                         g[i] = (g[0] + g[i]) & (((deUint32)1 << epBits[mode]) - 1);
2155                         b[i] = signExtend(b[i], deltaBitsB, 32);
2156                         b[i] = (b[0] + b[i]) & (((deUint32)1 << epBits[mode]) - 1);
2157                 }
2158         }
2159
2160         if (hasSign)
2161         {
2162                 for (deUint32 i = 1; i < 4; i++)
2163                 {
2164                         r[i] = signExtend(r[i], epBits[mode], 32);
2165                         g[i] = signExtend(g[i], epBits[mode], 32);
2166                         b[i] = signExtend(b[i], epBits[mode], 32);
2167                 }
2168         }
2169
2170         for (deUint32 i = 0; i < numEndpoints; i++)
2171         {
2172                 r[i] = unquantize(r[i], mode, hasSign);
2173                 g[i] = unquantize(g[i], mode, hasSign);
2174                 b[i] = unquantize(b[i], mode, hasSign);
2175         }
2176
2177         for (deUint32 i = 0; i < 16; i++)
2178         {
2179                 const deUint32  subsetIndex             = (numRegions == 1 ? 0 : partitions2[d][i]);
2180                 const deUint32  bits                    = (i == anchorIndex[subsetIndex]) ? (colorIndexBC - 1) : colorIndexBC;
2181                 const deUint32  colorIndex              = (deUint32)(colorIndexData & ((1 << bits) - 1));
2182                 const deInt32   endpointStartR  = r[2 * subsetIndex];
2183                 const deInt32   endpointEndR    = r[2 * subsetIndex + 1];
2184                 const deInt32   endpointStartG  = g[2 * subsetIndex];
2185                 const deInt32   endpointEndG    = g[2 * subsetIndex + 1];
2186                 const deInt32   endpointStartB  = b[2 * subsetIndex];
2187                 const deInt32   endpointEndB    = b[2 * subsetIndex + 1];
2188                 const deInt16   r16                             = finishUnquantize(interpolate(endpointStartR, endpointEndR, colorIndex, colorIndexBC), hasSign);
2189                 const deInt16   g16                             = finishUnquantize(interpolate(endpointStartG, endpointEndG, colorIndex, colorIndexBC), hasSign);
2190                 const deInt16   b16                             = finishUnquantize(interpolate(endpointStartB, endpointEndB, colorIndex, colorIndexBC), hasSign);
2191                 const deInt32   y                               = i / 4;
2192                 const deInt32   x                               = i % 4;
2193                 deInt16* const  dstPixel                = (deInt16*)(dstPtr + y * dstRowPitch + x * dstPixelSize);
2194
2195                 if (mode == -1)
2196                 {
2197                         dstPixel[0] = 0;
2198                         dstPixel[1] = 0;
2199                         dstPixel[2] = 0;
2200                 }
2201                 else
2202                 {
2203                         dstPixel[0] = r16;
2204                         dstPixel[1] = g16;
2205                         dstPixel[2] = b16;
2206                 }
2207
2208                 colorIndexData >>= bits;
2209         }
2210 }
2211
2212 void decompressBc7 (const PixelBufferAccess& dst, const deUint8* src)
2213 {
2214         using namespace BcDecompressInternal;
2215
2216         static const deUint8    subsets[]                       = { 3, 2, 3, 2, 1, 1, 1, 2 };
2217         static const deUint8    partitionBits[]         = { 4, 6, 6, 6, 0, 0, 0, 6 };
2218         static const deUint8    endpointBits[8][5]      =
2219         {
2220                 //r, g, b, a, p
2221                 { 4, 4, 4, 0, 1 },
2222                 { 6, 6, 6, 0, 1 },
2223                 { 5, 5, 5, 0, 0 },
2224                 { 7, 7, 7, 0, 1 },
2225                 { 5, 5, 5, 6, 0 },
2226                 { 7, 7, 7, 8, 0 },
2227                 { 7, 7, 7, 7, 1 },
2228                 { 5, 5, 5, 5, 1 }
2229         };
2230         static const deUint8    indexBits[]                     = { 3, 3, 2, 2, 2, 2, 4, 2 };
2231
2232         deUint8* const                  dstPtr                          = (deUint8*)dst.getDataPtr();
2233         const deUint32                  dstRowPitch                     = dst.getRowPitch();
2234         const deUint32                  dstPixelSize            = 4;
2235
2236         const deUint64                  low                                     = ((deUint64*)src)[0];
2237         const deUint64                  high                            = ((deUint64*)src)[1];
2238         const deInt32                   mode                            = extractModeBc7(src[0]);
2239         deUint32                                numSubsets                      = 1;
2240         deUint32                                offset                          = mode + 1;
2241         deUint32                                rotation                        = 0;
2242         deUint32                                idxMode                         = 0;
2243         deUint32                                endpoints[6][5];
2244         deUint32                                partitionSetId          = 0;
2245
2246         // Decode partition data from explicit partition bits
2247         if (mode == 0 || mode == 1 || mode == 2 || mode == 3 || mode == 7)
2248         {
2249                 numSubsets = subsets[mode];
2250                 partitionSetId = getBits128(low, high, offset, offset + partitionBits[mode] - 1);
2251                 offset += partitionBits[mode];
2252         }
2253
2254         // Extract rotation bits
2255         if (mode == 4 || mode == 5)
2256         {
2257                 rotation = getBits128(low, high, offset, offset + 1);
2258                 offset += 2;
2259                 if (mode == 4)
2260                 {
2261                         idxMode = getBits128(low, high, offset, offset);
2262                         offset++;
2263                 }
2264         }
2265
2266         {
2267                 const deUint32 numEndpoints = numSubsets * 2;
2268
2269                 // Extract raw, compressed endpoint bits
2270                 for (deUint32 cpnt = 0; cpnt < 5; cpnt++)
2271                 {
2272                         for (deUint32 ep = 0; ep < numEndpoints; ep++)
2273                         {
2274                                 if (mode == 1 && cpnt == 4 && ep > 1)
2275                                         continue; // Mode 1 has shared P bits
2276
2277                                 int n = mode == -1 ? 0 : endpointBits[mode][cpnt];
2278                                 if (n > 0)
2279                                         endpoints[ep][cpnt] = getBits128(low, high, offset, offset + n - 1);
2280                                 offset += n;
2281                         }
2282                 }
2283
2284                 // Decode endpoints
2285                 if (mode == 0 || mode == 1 || mode == 3 || mode == 6 || mode == 7)
2286                 {
2287                         // First handle modes that have P-bits
2288                         for (deUint32 ep = 0; ep < numEndpoints; ep++)
2289                         {
2290                                 for (deUint32 cpnt = 0; cpnt < 4; cpnt++)
2291                                 {
2292                                         endpoints[ep][cpnt] <<= 1;
2293                                 }
2294                         }
2295
2296                         if (mode == 1)
2297                         {
2298                                 // P-bit is shared
2299                                 const deUint32 pbitZero = endpoints[0][4];
2300                                 const deUint32 pbitOne  = endpoints[1][4];
2301
2302                                 for (deUint32 cpnt = 0; cpnt < 3; cpnt++)
2303                                 {
2304                                         endpoints[0][cpnt] |= pbitZero;
2305                                         endpoints[1][cpnt] |= pbitZero;
2306                                         endpoints[2][cpnt] |= pbitOne;
2307                                         endpoints[3][cpnt] |= pbitOne;
2308                                 }
2309                         }
2310                         else
2311                         {
2312                                 // Unique p-bit per endpoint
2313                                 for (deUint32 ep = 0; ep < numEndpoints; ep++)
2314                                 {
2315                                         for (deUint32 cpnt = 0; cpnt < 4; cpnt++)
2316                                         {
2317                                                 endpoints[ep][cpnt] |= endpoints[ep][4];
2318                                         }
2319                                 }
2320                         }
2321                 }
2322
2323                 for (deUint32 ep = 0; ep < numEndpoints; ep++)
2324                 {
2325                         // Left shift endpoint components so that their MSB lies in bit 7
2326                         for (deUint32 cpnt = 0; cpnt < 4; cpnt++)
2327                                 endpoints[ep][cpnt] <<= 8 - (endpointBits[mode][cpnt] + endpointBits[mode][4]);
2328
2329                         // Replicate each component's MSB into the LSBs revealed by the left-shift operation above
2330                         for (deUint32 cpnt = 0; cpnt < 4; cpnt++)
2331                                 endpoints[ep][cpnt] |= endpoints[ep][cpnt] >> (endpointBits[mode][cpnt] + endpointBits[mode][4]);
2332                 }
2333
2334                 // If this mode does not explicitly define the alpha component set alpha equal to 1.0
2335                 if (mode < 4)
2336                 {
2337                         for (deUint32 ep = 0; ep < numEndpoints; ep++)
2338                                 endpoints[ep][3] = 255;
2339                 }
2340         }
2341
2342         {
2343                 deUint32 colorIdxOffset = offset + ((mode == 4 && idxMode) ? 31 : 0);
2344                 deUint32 alphaIdxOffset = offset + ((mode == 5 || (mode == 4 && !idxMode)) ? 31 : 0);
2345
2346                 for (deUint32 pixel = 0; pixel < 16; pixel++)
2347                 {
2348                         const deUint32  y                               = pixel / 4;
2349                         const deUint32  x                               = pixel % 4;
2350                         deUint32* const dstPixel                = (deUint32*)(dstPtr + y * dstRowPitch + x * dstPixelSize);
2351                         deUint32                subsetIndex             = 0;
2352                         deUint32                anchorIndex             = 0;
2353                         deUint32                endpointStart[4];
2354                         deUint32                endpointEnd[4];
2355
2356                         if (mode == -1)
2357                         {
2358                                 *dstPixel = 0;
2359                                 continue;
2360                         }
2361
2362                         if (numSubsets == 2)
2363                                 subsetIndex = partitions2[partitionSetId][pixel];
2364                         else if (numSubsets == 3)
2365                                 subsetIndex = partitions3[partitionSetId][pixel];
2366
2367                         if (numSubsets == 2 && subsetIndex == 1)
2368                         {
2369                                 anchorIndex = anchorIndicesSecondSubset2[partitionSetId];
2370                         }
2371                         else if (numSubsets == 3)
2372                         {
2373                                 if (subsetIndex == 1)
2374                                         anchorIndex = anchorIndicesSecondSubset3[partitionSetId];
2375                                 else if (subsetIndex == 2)
2376                                         anchorIndex = anchorIndicesThirdSubset[partitionSetId];
2377                         }
2378
2379                         for (deUint32 cpnt = 0; cpnt < 4; cpnt++)
2380                         {
2381                                 endpointStart[cpnt] = endpoints[2 * subsetIndex][cpnt];
2382                                 endpointEnd[cpnt] = endpoints[2 * subsetIndex + 1][cpnt];
2383                         }
2384
2385                         {
2386                                 const deUint32 colorInterpolationBits   = indexBits[mode] + idxMode;
2387                                 const deUint32 colorIndexBits                   = colorInterpolationBits - ((anchorIndex == pixel) ? 1 : 0);
2388                                 const deUint32 alphaInterpolationBits   = mode == 4 ? 3 - idxMode : (mode == 5 ? 2 : colorInterpolationBits);
2389                                 const deUint32 alphaIndexBits                   = alphaInterpolationBits - ((anchorIndex == pixel) ? 1 : 0);
2390                                 const deUint32 colorIdx                                 = getBits128(low, high, colorIdxOffset, colorIdxOffset + colorIndexBits - 1);
2391                                 const deUint32 alphaIdx                                 = (mode == 4 || mode == 5) ? getBits128(low, high, alphaIdxOffset, alphaIdxOffset + alphaIndexBits - 1) : colorIdx;
2392                                 const deUint32 r                                                = interpolate(endpointStart[0], endpointEnd[0], colorIdx, colorInterpolationBits);
2393                                 const deUint32 g                                                = interpolate(endpointStart[1], endpointEnd[1], colorIdx, colorInterpolationBits);
2394                                 const deUint32 b                                                = interpolate(endpointStart[2], endpointEnd[2], colorIdx, colorInterpolationBits);
2395                                 const deUint32 a                                                = interpolate(endpointStart[3], endpointEnd[3], alphaIdx, alphaInterpolationBits);
2396
2397                                 colorIdxOffset += colorIndexBits;
2398                                 alphaIdxOffset += alphaIndexBits;
2399
2400                                 if ((mode == 4 || mode == 5) && rotation != 0)
2401                                 {
2402                                         if (rotation == 1)
2403                                                 *dstPixel = a | (g << 8) | (b << 16) | (r << 24);
2404                                         else if (rotation == 2)
2405                                                 *dstPixel = r | (a << 8) | (b << 16) | (g << 24);
2406                                         else
2407                                                 *dstPixel = r | (g << 8) | (a << 16) | (b << 24);
2408                                 }
2409                                 else
2410                                 {
2411                                         *dstPixel = r | (g << 8) | (b << 16) | (a << 24);
2412                                 }
2413                         }
2414                 }
2415         }
2416 }
2417
2418 void decompressBlock (CompressedTexFormat format, const PixelBufferAccess& dst, const deUint8* src, const TexDecompressionParams& params)
2419 {
2420         // No 3D blocks supported right now
2421         DE_ASSERT(dst.getDepth() == 1);
2422
2423         switch (format)
2424         {
2425                 case COMPRESSEDTEXFORMAT_ETC1_RGB8:                                                     decompressETC1                                                  (dst, src);                     break;
2426                 case COMPRESSEDTEXFORMAT_EAC_R11:                                                       decompressEAC_R11                                               (dst, src, false);      break;
2427                 case COMPRESSEDTEXFORMAT_EAC_SIGNED_R11:                                        decompressEAC_R11                                               (dst, src, true);       break;
2428                 case COMPRESSEDTEXFORMAT_EAC_RG11:                                                      decompressEAC_RG11                                              (dst, src, false);      break;
2429                 case COMPRESSEDTEXFORMAT_EAC_SIGNED_RG11:                                       decompressEAC_RG11                                              (dst, src, true);       break;
2430                 case COMPRESSEDTEXFORMAT_ETC2_RGB8:                                                     decompressETC2                                                  (dst, src);                     break;
2431                 case COMPRESSEDTEXFORMAT_ETC2_SRGB8:                                            decompressETC2                                                  (dst, src);                     break;
2432                 case COMPRESSEDTEXFORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:         decompressETC2_RGB8_PUNCHTHROUGH_ALPHA1 (dst, src);                     break;
2433                 case COMPRESSEDTEXFORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:        decompressETC2_RGB8_PUNCHTHROUGH_ALPHA1 (dst, src);                     break;
2434                 case COMPRESSEDTEXFORMAT_ETC2_EAC_RGBA8:                                        decompressETC2_EAC_RGBA8                                (dst, src);                     break;
2435                 case COMPRESSEDTEXFORMAT_ETC2_EAC_SRGB8_ALPHA8:                         decompressETC2_EAC_RGBA8                                (dst, src);                     break;
2436
2437                 case COMPRESSEDTEXFORMAT_ASTC_4x4_RGBA:
2438                 case COMPRESSEDTEXFORMAT_ASTC_5x4_RGBA:
2439                 case COMPRESSEDTEXFORMAT_ASTC_5x5_RGBA:
2440                 case COMPRESSEDTEXFORMAT_ASTC_6x5_RGBA:
2441                 case COMPRESSEDTEXFORMAT_ASTC_6x6_RGBA:
2442                 case COMPRESSEDTEXFORMAT_ASTC_8x5_RGBA:
2443                 case COMPRESSEDTEXFORMAT_ASTC_8x6_RGBA:
2444                 case COMPRESSEDTEXFORMAT_ASTC_8x8_RGBA:
2445                 case COMPRESSEDTEXFORMAT_ASTC_10x5_RGBA:
2446                 case COMPRESSEDTEXFORMAT_ASTC_10x6_RGBA:
2447                 case COMPRESSEDTEXFORMAT_ASTC_10x8_RGBA:
2448                 case COMPRESSEDTEXFORMAT_ASTC_10x10_RGBA:
2449                 case COMPRESSEDTEXFORMAT_ASTC_12x10_RGBA:
2450                 case COMPRESSEDTEXFORMAT_ASTC_12x12_RGBA:
2451                 case COMPRESSEDTEXFORMAT_ASTC_4x4_SRGB8_ALPHA8:
2452                 case COMPRESSEDTEXFORMAT_ASTC_5x4_SRGB8_ALPHA8:
2453                 case COMPRESSEDTEXFORMAT_ASTC_5x5_SRGB8_ALPHA8:
2454                 case COMPRESSEDTEXFORMAT_ASTC_6x5_SRGB8_ALPHA8:
2455                 case COMPRESSEDTEXFORMAT_ASTC_6x6_SRGB8_ALPHA8:
2456                 case COMPRESSEDTEXFORMAT_ASTC_8x5_SRGB8_ALPHA8:
2457                 case COMPRESSEDTEXFORMAT_ASTC_8x6_SRGB8_ALPHA8:
2458                 case COMPRESSEDTEXFORMAT_ASTC_8x8_SRGB8_ALPHA8:
2459                 case COMPRESSEDTEXFORMAT_ASTC_10x5_SRGB8_ALPHA8:
2460                 case COMPRESSEDTEXFORMAT_ASTC_10x6_SRGB8_ALPHA8:
2461                 case COMPRESSEDTEXFORMAT_ASTC_10x8_SRGB8_ALPHA8:
2462                 case COMPRESSEDTEXFORMAT_ASTC_10x10_SRGB8_ALPHA8:
2463                 case COMPRESSEDTEXFORMAT_ASTC_12x10_SRGB8_ALPHA8:
2464                 case COMPRESSEDTEXFORMAT_ASTC_12x12_SRGB8_ALPHA8:
2465                         astc::decompress(dst, src, format, params.astcMode);
2466                         break;
2467
2468                 case COMPRESSEDTEXFORMAT_BC1_RGB_UNORM_BLOCK:                           decompressBc1                                                   (dst, src, false);      break;
2469                 case COMPRESSEDTEXFORMAT_BC1_RGB_SRGB_BLOCK:                            decompressBc1                                                   (dst, src, false);      break;
2470                 case COMPRESSEDTEXFORMAT_BC1_RGBA_UNORM_BLOCK:                          decompressBc1                                                   (dst, src, true);       break;
2471                 case COMPRESSEDTEXFORMAT_BC1_RGBA_SRGB_BLOCK:                           decompressBc1                                                   (dst, src, true);       break;
2472                 case COMPRESSEDTEXFORMAT_BC2_UNORM_BLOCK:                                       decompressBc2                                                   (dst, src);                     break;
2473                 case COMPRESSEDTEXFORMAT_BC2_SRGB_BLOCK:                                        decompressBc2                                                   (dst, src);                     break;
2474                 case COMPRESSEDTEXFORMAT_BC3_UNORM_BLOCK:                                       decompressBc3                                                   (dst, src);                     break;
2475                 case COMPRESSEDTEXFORMAT_BC3_SRGB_BLOCK:                                        decompressBc3                                                   (dst, src);                     break;
2476                 case COMPRESSEDTEXFORMAT_BC4_UNORM_BLOCK:                                       decompressBc4                                                   (dst, src, false);      break;
2477                 case COMPRESSEDTEXFORMAT_BC4_SNORM_BLOCK:                                       decompressBc4                                                   (dst, src, true);       break;
2478                 case COMPRESSEDTEXFORMAT_BC5_UNORM_BLOCK:                                       decompressBc5                                                   (dst, src, false);      break;
2479                 case COMPRESSEDTEXFORMAT_BC5_SNORM_BLOCK:                                       decompressBc5                                                   (dst, src, true);       break;
2480                 case COMPRESSEDTEXFORMAT_BC6H_UFLOAT_BLOCK:                                     decompressBc6H                                                  (dst, src, false);      break;
2481                 case COMPRESSEDTEXFORMAT_BC6H_SFLOAT_BLOCK:                                     decompressBc6H                                                  (dst, src, true);       break;
2482                 case COMPRESSEDTEXFORMAT_BC7_UNORM_BLOCK:                                       decompressBc7                                                   (dst, src);                     break;
2483                 case COMPRESSEDTEXFORMAT_BC7_SRGB_BLOCK:                                        decompressBc7                                                   (dst, src);                     break;
2484
2485                 default:
2486                         DE_FATAL("Unexpected format");
2487                         break;
2488         }
2489 }
2490
2491 int componentSum (const IVec3& vec)
2492 {
2493         return vec.x() + vec.y() + vec.z();
2494 }
2495
2496 } // anonymous
2497
2498 void decompress (const PixelBufferAccess& dst, CompressedTexFormat fmt, const deUint8* src, const TexDecompressionParams& params)
2499 {
2500         const int                               blockSize                       = getBlockSize(fmt);
2501         const IVec3                             blockPixelSize          (getBlockPixelSize(fmt));
2502         const IVec3                             blockCount                      (deDivRoundUp32(dst.getWidth(),         blockPixelSize.x()),
2503                                                                                                  deDivRoundUp32(dst.getHeight(),        blockPixelSize.y()),
2504                                                                                                  deDivRoundUp32(dst.getDepth(),         blockPixelSize.z()));
2505         const IVec3                             blockPitches            (blockSize, blockSize * blockCount.x(), blockSize * blockCount.x() * blockCount.y());
2506
2507         std::vector<deUint8>    uncompressedBlock       (dst.getFormat().getPixelSize() * blockPixelSize.x() * blockPixelSize.y() * blockPixelSize.z());
2508         const PixelBufferAccess blockAccess                     (getUncompressedFormat(fmt), blockPixelSize.x(), blockPixelSize.y(), blockPixelSize.z(), &uncompressedBlock[0]);
2509
2510         DE_ASSERT(dst.getFormat() == getUncompressedFormat(fmt));
2511
2512         for (int blockZ = 0; blockZ < blockCount.z(); blockZ++)
2513         for (int blockY = 0; blockY < blockCount.y(); blockY++)
2514         for (int blockX = 0; blockX < blockCount.x(); blockX++)
2515         {
2516                 const IVec3                             blockPos        (blockX, blockY, blockZ);
2517                 const deUint8* const    blockPtr        = src + componentSum(blockPos * blockPitches);
2518                 const IVec3                             copySize        (de::min(blockPixelSize.x(), dst.getWidth()             - blockPos.x() * blockPixelSize.x()),
2519                                                                                          de::min(blockPixelSize.y(), dst.getHeight()    - blockPos.y() * blockPixelSize.y()),
2520                                                                                          de::min(blockPixelSize.z(), dst.getDepth()             - blockPos.z() * blockPixelSize.z()));
2521                 const IVec3                             dstPixelPos     = blockPos * blockPixelSize;
2522
2523                 decompressBlock(fmt, blockAccess, blockPtr, params);
2524
2525                 copy(getSubregion(dst, dstPixelPos.x(), dstPixelPos.y(), dstPixelPos.z(), copySize.x(), copySize.y(), copySize.z()), getSubregion(blockAccess, 0, 0, 0, copySize.x(), copySize.y(), copySize.z()));
2526         }
2527 }
2528
2529 CompressedTexture::CompressedTexture (void)
2530         : m_format      (COMPRESSEDTEXFORMAT_LAST)
2531         , m_width       (0)
2532         , m_height      (0)
2533         , m_depth       (0)
2534 {
2535 }
2536
2537 CompressedTexture::CompressedTexture (CompressedTexFormat format, int width, int height, int depth)
2538         : m_format      (COMPRESSEDTEXFORMAT_LAST)
2539         , m_width       (0)
2540         , m_height      (0)
2541         , m_depth       (0)
2542 {
2543         setStorage(format, width, height, depth);
2544 }
2545
2546 CompressedTexture::~CompressedTexture (void)
2547 {
2548 }
2549
2550 void CompressedTexture::setStorage (CompressedTexFormat format, int width, int height, int depth)
2551 {
2552         m_format        = format;
2553         m_width         = width;
2554         m_height        = height;
2555         m_depth         = depth;
2556
2557         if (m_format != COMPRESSEDTEXFORMAT_LAST)
2558         {
2559                 const IVec3     blockPixelSize  = getBlockPixelSize(m_format);
2560                 const int       blockSize               = getBlockSize(m_format);
2561
2562                 m_data.resize(deDivRoundUp32(m_width, blockPixelSize.x()) * deDivRoundUp32(m_height, blockPixelSize.y()) * deDivRoundUp32(m_depth, blockPixelSize.z()) * blockSize);
2563         }
2564         else
2565         {
2566                 DE_ASSERT(m_format == COMPRESSEDTEXFORMAT_LAST);
2567                 DE_ASSERT(m_width == 0 && m_height == 0 && m_depth == 0);
2568                 m_data.resize(0);
2569         }
2570 }
2571
2572 /*--------------------------------------------------------------------*//*!
2573  * \brief Decode to uncompressed pixel data
2574  * \param dst Destination buffer
2575  *//*--------------------------------------------------------------------*/
2576 void CompressedTexture::decompress (const PixelBufferAccess& dst, const TexDecompressionParams& params) const
2577 {
2578         DE_ASSERT(dst.getWidth() == m_width && dst.getHeight() == m_height && dst.getDepth() == m_depth);
2579         DE_ASSERT(dst.getFormat() == getUncompressedFormat(m_format));
2580
2581         tcu::decompress(dst, m_format, &m_data[0], params);
2582 }
2583
2584 } // tcu