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
33namespace tcu
34{
35
36int 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
96IVec3 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
151bool 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
173bool 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
200bool 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
215bool 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
231bool 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
270bool 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
295TextureFormat 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
345CompressedTexFormat 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
361namespace
362{
363
364inline deUint8 extend4To8 (deUint8 src)
365{
366	DE_ASSERT((src & ~((1<<4)-1)) == 0);
367	return (deUint8)((src << 4) | src);
368}
369
370inline deUint8 extend5To8 (deUint8 src)
371{
372	DE_ASSERT((src & ~((1<<5)-1)) == 0);
373	return (deUint8)((src << 3) | (src >> 2));
374}
375
376inline 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
384namespace EtcDecompressInternal
385{
386
387enum
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
403inline 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.
415inline 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.
421inline deUint64 get128BitBlockEnd (const deUint8* src, int blockNdx)
422{
423	return get64BitBlock(src, 2*blockNdx + 1);
424}
425
426inline deUint32 getBit (deUint64 src, int bit)
427{
428	return (src >> bit) & 1;
429}
430
431inline 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
441inline deUint8 extend7To8 (deUint8 src)
442{
443	DE_ASSERT((src & ~((1<<7)-1)) == 0);
444	return (deUint8)((src << 1) | (src >> 6));
445}
446
447inline deInt8 extendSigned3To8 (deUint8 src)
448{
449	const bool isNeg = (src & (1<<2)) != 0;
450	return (deInt8)((isNeg ? ~((1<<3)-1) : 0) | src);
451}
452
453inline deUint8 extend5Delta3To8 (deUint8 base5, deUint8 delta3)
454{
455	const deUint8 t = (deUint8)((deInt8)base5 + extendSigned3To8(delta3));
456	return extend5To8(t);
457}
458
459inline deUint16 extend11To16 (deUint16 src)
460{
461	DE_ASSERT((src & ~((1<<11)-1)) == 0);
462	return (deUint16)((src << 5) | (src >> 6));
463}
464
465inline 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
473void 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.
542void 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
804void 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
843void 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
913void 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
923void 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
933void 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
968void 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
1001void 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
1040void 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
1086namespace BcDecompressInternal
1087{
1088
1089enum
1090{
1091	BC_BLOCK_WIDTH	= 4,
1092	BC_BLOCK_HEIGHT	= 4
1093};
1094
1095static const deUint8	epBits[14]						= { 10, 7, 11, 11, 11, 9, 8, 8, 8, 6, 10, 11, 12, 16 };
1096
1097static 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
1165static 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
1233static 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
1236static 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
1239static 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
1242static const deUint16	weights2[4]						= { 0, 21, 43, 64 };
1243static const deUint16	weights3[8]						= { 0, 9, 18, 27, 37, 46, 55, 64 };
1244static const deUint16	weights4[16]					= { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 };
1245
1246inline float uint8ToFloat (deUint8 src)
1247{
1248	return ((float)src / 255.0f);
1249}
1250
1251inline float int8ToFloat (deInt8 src)
1252{
1253	return ((float)src / 128.0f);
1254}
1255
1256inline 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
1271inline 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
1292inline 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
1312inline 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
1335inline 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
1344inline 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
1355inline 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
1408inline 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
1419inline 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
1458inline 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
1467inline 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
1489void 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
1542void 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
1614void 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
1705void 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
1765void 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
1815void 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
2212void 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
2418void 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
2491int componentSum (const IVec3& vec)
2492{
2493	return vec.x() + vec.y() + vec.z();
2494}
2495
2496} // anonymous
2497
2498void 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
2529CompressedTexture::CompressedTexture (void)
2530	: m_format	(COMPRESSEDTEXFORMAT_LAST)
2531	, m_width	(0)
2532	, m_height	(0)
2533	, m_depth	(0)
2534{
2535}
2536
2537CompressedTexture::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
2546CompressedTexture::~CompressedTexture (void)
2547{
2548}
2549
2550void 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 *//*--------------------------------------------------------------------*/
2576void 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