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