• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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