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