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