13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program Tester Core
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ----------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Compressed Texture Utilities.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuCompressedTexture.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuTextureUtil.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deStringUtil.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deFloat16.h"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <algorithm>
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace tcu
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum { ASTC_BLOCK_SIZE_BYTES = 128/8 };
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, typename Y>
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct isSameType			{ enum { V = 0 }; };
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T>
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct isSameType<T, T>		{ enum { V = 1 }; };
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
413c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCompressedTexture::CompressedTexture (void)
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_format	(FORMAT_LAST)
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_width	(0)
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_height	(0)
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_depth	(0)
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
493c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCompressedTexture::CompressedTexture (Format format, int width, int height, int depth)
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_format	(FORMAT_LAST)
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_width	(0)
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_height	(0)
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_depth	(0)
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	setStorage(format, width, height, depth);
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
583c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCompressedTexture::~CompressedTexture (void)
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline int divRoundUp (int a, int b)
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return a/b + ((a%b) ? 1 : 0);
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool isEtcFormat (CompressedTexture::Format fmt)
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (fmt)
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ETC1_RGB8:
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::EAC_R11:
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::EAC_SIGNED_R11:
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::EAC_RG11:
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::EAC_SIGNED_RG11:
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ETC2_RGB8:
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ETC2_SRGB8:
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ETC2_EAC_RGBA8:
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ETC2_EAC_SRGB8_ALPHA8:
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool isASTCFormat (CompressedTexture::Format fmt)
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (fmt)
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_4x4_RGBA:
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_5x4_RGBA:
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_5x5_RGBA:
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_6x5_RGBA:
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_6x6_RGBA:
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_8x5_RGBA:
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_8x6_RGBA:
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_8x8_RGBA:
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x5_RGBA:
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x6_RGBA:
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x8_RGBA:
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x10_RGBA:
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_12x10_RGBA:
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_12x12_RGBA:
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_4x4_SRGB8_ALPHA8:
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_5x4_SRGB8_ALPHA8:
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_5x5_SRGB8_ALPHA8:
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_6x5_SRGB8_ALPHA8:
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_6x6_SRGB8_ALPHA8:
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_8x5_SRGB8_ALPHA8:
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_8x6_SRGB8_ALPHA8:
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_8x8_SRGB8_ALPHA8:
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x5_SRGB8_ALPHA8:
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x6_SRGB8_ALPHA8:
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x8_SRGB8_ALPHA8:
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x10_SRGB8_ALPHA8:
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_12x10_SRGB8_ALPHA8:
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_12x12_SRGB8_ALPHA8:
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool isASTCSRGBFormat (CompressedTexture::Format fmt)
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (fmt)
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_4x4_SRGB8_ALPHA8:
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_5x4_SRGB8_ALPHA8:
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_5x5_SRGB8_ALPHA8:
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_6x5_SRGB8_ALPHA8:
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_6x6_SRGB8_ALPHA8:
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_8x5_SRGB8_ALPHA8:
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_8x6_SRGB8_ALPHA8:
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_8x8_SRGB8_ALPHA8:
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x5_SRGB8_ALPHA8:
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x6_SRGB8_ALPHA8:
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x8_SRGB8_ALPHA8:
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x10_SRGB8_ALPHA8:
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_12x10_SRGB8_ALPHA8:
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_12x12_SRGB8_ALPHA8:
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1533c827367444ee418f129b2c238299f49d3264554Jarkko PoyryIVec3 getASTCBlockSize (CompressedTexture::Format fmt)
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (fmt)
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_4x4_RGBA:				return IVec3(4,  4,  1);
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_5x4_RGBA:				return IVec3(5,  4,  1);
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_5x5_RGBA:				return IVec3(5,  5,  1);
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_6x5_RGBA:				return IVec3(6,  5,  1);
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_6x6_RGBA:				return IVec3(6,  6,  1);
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_8x5_RGBA:				return IVec3(8,  5,  1);
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_8x6_RGBA:				return IVec3(8,  6,  1);
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_8x8_RGBA:				return IVec3(8,  8,  1);
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x5_RGBA:				return IVec3(10, 5,  1);
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x6_RGBA:				return IVec3(10, 6,  1);
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x8_RGBA:				return IVec3(10, 8,  1);
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x10_RGBA:			return IVec3(10, 10, 1);
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_12x10_RGBA:			return IVec3(12, 10, 1);
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_12x12_RGBA:			return IVec3(12, 12, 1);
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_4x4_SRGB8_ALPHA8:		return IVec3(4,  4,  1);
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_5x4_SRGB8_ALPHA8:		return IVec3(5,  4,  1);
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_5x5_SRGB8_ALPHA8:		return IVec3(5,  5,  1);
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_6x5_SRGB8_ALPHA8:		return IVec3(6,  5,  1);
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_6x6_SRGB8_ALPHA8:		return IVec3(6,  6,  1);
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_8x5_SRGB8_ALPHA8:		return IVec3(8,  5,  1);
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_8x6_SRGB8_ALPHA8:		return IVec3(8,  6,  1);
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_8x8_SRGB8_ALPHA8:		return IVec3(8,  8,  1);
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x5_SRGB8_ALPHA8:		return IVec3(10, 5,  1);
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x6_SRGB8_ALPHA8:		return IVec3(10, 6,  1);
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x8_SRGB8_ALPHA8:		return IVec3(10, 8,  1);
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_10x10_SRGB8_ALPHA8:	return IVec3(10, 10, 1);
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_12x10_SRGB8_ALPHA8:	return IVec3(12, 10, 1);
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case CompressedTexture::ASTC_12x12_SRGB8_ALPHA8:	return IVec3(12, 12, 1);
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return IVec3();
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1923c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCompressedTexture::Format getASTCFormatByBlockSize (int width, int height, int depth, bool isSRGB)
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (depth > 1)
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::InternalError("3D ASTC textures not currently supported");
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const tcu::IVec3 size(width, height, depth);
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int fmtI = 0; fmtI < CompressedTexture::FORMAT_LAST; fmtI++)
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const CompressedTexture::Format fmt = (CompressedTexture::Format)fmtI;
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isASTCFormat(fmt) && getASTCBlockSize(fmt) == size && isASTCSRGBFormat(fmt) == isSRGB)
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return fmt;
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	throw tcu::InternalError("Invalid ASTC block size " + de::toString(width) + "x" + de::toString(height) + "x" + de::toString(depth));
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CompressedTexture::setStorage (Format format, int width, int height, int depth)
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_format	= format;
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_width		= width;
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_height	= height;
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_depth		= depth;
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isEtcFormat(m_format))
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_depth == 1);
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int blockSizeMultiplier = 0; // How many 64-bit parts each compressed block contains.
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (m_format)
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case ETC1_RGB8:							blockSizeMultiplier = 1;	break;
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case EAC_R11:							blockSizeMultiplier = 1;	break;
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case EAC_SIGNED_R11:					blockSizeMultiplier = 1;	break;
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case EAC_RG11:							blockSizeMultiplier = 2;	break;
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case EAC_SIGNED_RG11:					blockSizeMultiplier = 2;	break;
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case ETC2_RGB8:							blockSizeMultiplier = 1;	break;
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case ETC2_SRGB8:						blockSizeMultiplier = 1;	break;
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case ETC2_RGB8_PUNCHTHROUGH_ALPHA1:		blockSizeMultiplier = 1;	break;
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:	blockSizeMultiplier = 1;	break;
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case ETC2_EAC_RGBA8:					blockSizeMultiplier = 2;	break;
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case ETC2_EAC_SRGB8_ALPHA8:				blockSizeMultiplier = 2;	break;
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_data.resize(blockSizeMultiplier * sizeof(deUint64) * divRoundUp(m_width, 4) * divRoundUp(m_height, 4));
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (isASTCFormat(m_format))
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_depth > 1)
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw tcu::InternalError("3D ASTC textures not currently supported");
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const IVec3 blockSize = getASTCBlockSize(m_format);
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_data.resize(ASTC_BLOCK_SIZE_BYTES * divRoundUp(m_width, blockSize.x()) * divRoundUp(m_height, blockSize.y()) * divRoundUp(m_depth, blockSize.z()));
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_format == FORMAT_LAST);
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_width == 0 && m_height == 0 && m_depth == 0);
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_data.resize(0);
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Get uncompressed texture format
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
2633c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTextureFormat CompressedTexture::getUncompressedFormat (void) const
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isEtcFormat(m_format))
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (m_format)
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case ETC1_RGB8:							return TextureFormat(TextureFormat::RGB,	TextureFormat::UNORM_INT8);
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case EAC_R11:							return TextureFormat(TextureFormat::R,		TextureFormat::UNORM_INT16);
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case EAC_SIGNED_R11:					return TextureFormat(TextureFormat::R,		TextureFormat::SNORM_INT16);
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case EAC_RG11:							return TextureFormat(TextureFormat::RG,		TextureFormat::UNORM_INT16);
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case EAC_SIGNED_RG11:					return TextureFormat(TextureFormat::RG,		TextureFormat::SNORM_INT16);
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case ETC2_RGB8:							return TextureFormat(TextureFormat::RGB,	TextureFormat::UNORM_INT8);
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case ETC2_SRGB8:						return TextureFormat(TextureFormat::sRGB,	TextureFormat::UNORM_INT8);
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case ETC2_RGB8_PUNCHTHROUGH_ALPHA1:		return TextureFormat(TextureFormat::RGBA,	TextureFormat::UNORM_INT8);
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:	return TextureFormat(TextureFormat::sRGBA,	TextureFormat::UNORM_INT8);
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case ETC2_EAC_RGBA8:					return TextureFormat(TextureFormat::RGBA,	TextureFormat::UNORM_INT8);
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case ETC2_EAC_SRGB8_ALPHA8:				return TextureFormat(TextureFormat::sRGBA,	TextureFormat::UNORM_INT8);
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return TextureFormat();
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (isASTCFormat(m_format))
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (isASTCSRGBFormat(m_format))
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return TextureFormat(TextureFormat::sRGBA, TextureFormat::UNORM_INT8);
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return TextureFormat(TextureFormat::RGBA, TextureFormat::HALF_FLOAT);
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(false);
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return TextureFormat();
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// \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?
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace EtcDecompressInternal
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ETC2_BLOCK_WIDTH					= 4,
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ETC2_BLOCK_HEIGHT					= 4,
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ETC2_UNCOMPRESSED_PIXEL_SIZE_A8		= 1,
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ETC2_UNCOMPRESSED_PIXEL_SIZE_R11	= 2,
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11	= 4,
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8	= 3,
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8	= 4,
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ETC2_UNCOMPRESSED_BLOCK_SIZE_A8		= ETC2_BLOCK_WIDTH*ETC2_BLOCK_HEIGHT*ETC2_UNCOMPRESSED_PIXEL_SIZE_A8,
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ETC2_UNCOMPRESSED_BLOCK_SIZE_R11	= ETC2_BLOCK_WIDTH*ETC2_BLOCK_HEIGHT*ETC2_UNCOMPRESSED_PIXEL_SIZE_R11,
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ETC2_UNCOMPRESSED_BLOCK_SIZE_RG11	= ETC2_BLOCK_WIDTH*ETC2_BLOCK_HEIGHT*ETC2_UNCOMPRESSED_PIXEL_SIZE_RG11,
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8	= ETC2_BLOCK_WIDTH*ETC2_BLOCK_HEIGHT*ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8,
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ETC2_UNCOMPRESSED_BLOCK_SIZE_RGBA8	= ETC2_BLOCK_WIDTH*ETC2_BLOCK_HEIGHT*ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deUint64 get64BitBlock (const deUint8* src, int blockNdx)
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Stored in big-endian form.
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint64 block = 0;
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < 8; i++)
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		block = (block << 8ull) | (deUint64)(src[blockNdx*8+i]);
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return block;
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Return the first 64 bits of a 128 bit block.
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deUint64 get128BitBlockStart (const deUint8* src, int blockNdx)
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return get64BitBlock(src, 2*blockNdx);
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Return the last 64 bits of a 128 bit block.
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deUint64 get128BitBlockEnd (const deUint8* src, int blockNdx)
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return get64BitBlock(src, 2*blockNdx + 1);
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deUint32 getBit (deUint64 src, int bit)
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (src >> bit) & 1;
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deUint32 getBits (deUint64 src, int low, int high)
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int numBits = (high-low) + 1;
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inRange(numBits, 1, 32));
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (src >> low) & ((1<<numBits)-1);
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deUint8 extend4To8 (deUint8 src)
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((src & ~((1<<4)-1)) == 0);
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (src << 4) | src;
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deUint8 extend5To8 (deUint8 src)
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((src & ~((1<<5)-1)) == 0);
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (src << 3) | (src >> 2);
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deUint8 extend6To8 (deUint8 src)
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((src & ~((1<<6)-1)) == 0);
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (src << 2) | (src >> 4);
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deUint8 extend7To8 (deUint8 src)
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((src & ~((1<<7)-1)) == 0);
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (src << 1) | (src >> 6);
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deInt8 extendSigned3To8 (deUint8 src)
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool isNeg = (src & (1<<2)) != 0;
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (deInt8)((isNeg ? ~((1<<3)-1) : 0) | src);
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deUint8 extend5Delta3To8 (deUint8 base5, deUint8 delta3)
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint8 t = (deUint8)((deInt8)base5 + extendSigned3To8(delta3));
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return extend5To8(t);
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deUint16 extend11To16 (deUint16 src)
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((src & ~((1<<11)-1)) == 0);
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (src << 5) | (src >> 6);
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline deInt16 extend11To16WithSign (deInt16 src)
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (src < 0)
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return -(deInt16)extend11To16(-src);
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return (deInt16)extend11To16(src);
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void decompressETC1Block (deUint8 dst[ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8], deUint64 src)
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		diffBit		= (int)getBit(src, 33);
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		flipBit		= (int)getBit(src, 32);
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	table[2]	= { getBits(src, 37, 39), getBits(src, 34, 36) };
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint8			baseR[2];
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint8			baseG[2];
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint8			baseB[2];
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (diffBit == 0)
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Individual mode.
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		baseR[0] = extend4To8((deUint8)getBits(src, 60, 63));
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		baseR[1] = extend4To8((deUint8)getBits(src, 56, 59));
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		baseG[0] = extend4To8((deUint8)getBits(src, 52, 55));
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		baseG[1] = extend4To8((deUint8)getBits(src, 48, 51));
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		baseB[0] = extend4To8((deUint8)getBits(src, 44, 47));
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		baseB[1] = extend4To8((deUint8)getBits(src, 40, 43));
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Differential mode (diffBit == 1).
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8 bR = (deUint8)getBits(src, 59, 63); // 5b
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8 dR = (deUint8)getBits(src, 56, 58); // 3b
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8 bG = (deUint8)getBits(src, 51, 55);
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8 dG = (deUint8)getBits(src, 48, 50);
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8 bB = (deUint8)getBits(src, 43, 47);
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8 dB = (deUint8)getBits(src, 40, 42);
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		baseR[0] = extend5To8(bR);
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		baseG[0] = extend5To8(bG);
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		baseB[0] = extend5To8(bB);
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		baseR[1] = extend5Delta3To8(bR, dR);
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		baseG[1] = extend5Delta3To8(bG, dG);
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		baseB[1] = extend5Delta3To8(bB, dB);
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int modifierTable[8][4] =
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	//	  00   01   10    11
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{  2,   8,  -2,   -8 },
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{  5,  17,  -5,  -17 },
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{  9,  29,  -9,  -29 },
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ 13,  42, -13,  -42 },
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ 18,  60, -18,  -60 },
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ 24,  80, -24,  -80 },
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ 33, 106, -33, -106 },
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{ 47, 183, -47, -183 }
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Write final pixels.
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int pixelNdx = 0; pixelNdx < ETC2_BLOCK_HEIGHT*ETC2_BLOCK_WIDTH; pixelNdx++)
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		x				= pixelNdx / ETC2_BLOCK_HEIGHT;
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		y				= pixelNdx % ETC2_BLOCK_HEIGHT;
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		dstOffset		= (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		subBlock		= ((flipBit ? y : x) >= 2) ? 1 : 0;
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint32	tableNdx		= table[subBlock];
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint32	modifierNdx		= (getBit(src, 16+pixelNdx) << 1) | getBit(src, pixelNdx);
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		modifier		= modifierTable[tableNdx][modifierNdx];
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst[dstOffset+0] = (deUint8)deClamp32((int)baseR[subBlock] + modifier, 0, 255);
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst[dstOffset+1] = (deUint8)deClamp32((int)baseG[subBlock] + modifier, 0, 255);
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst[dstOffset+2] = (deUint8)deClamp32((int)baseB[subBlock] + modifier, 0, 255);
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// if alphaMode is true, do PUNCHTHROUGH and store alpha to alphaDst; otherwise do ordinary ETC2 RGB8.
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void decompressETC2Block (deUint8 dst[ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8], deUint64 src, deUint8 alphaDst[ETC2_UNCOMPRESSED_BLOCK_SIZE_A8], bool alphaMode)
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum Etc2Mode
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		MODE_INDIVIDUAL = 0,
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		MODE_DIFFERENTIAL,
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		MODE_T,
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		MODE_H,
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		MODE_PLANAR,
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		MODE_LAST
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		diffOpaqueBit	= (int)getBit(src, 33);
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deInt8	selBR			= (deInt8)getBits(src, 59, 63);	// 5 bits.
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deInt8	selBG			= (deInt8)getBits(src, 51, 55);
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deInt8	selBB			= (deInt8)getBits(src, 43, 47);
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deInt8	selDR			= extendSigned3To8((deUint8)getBits(src, 56, 58)); // 3 bits.
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deInt8	selDG			= extendSigned3To8((deUint8)getBits(src, 48, 50));
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deInt8	selDB			= extendSigned3To8((deUint8)getBits(src, 40, 42));
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Etc2Mode		mode;
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!alphaMode && diffOpaqueBit == 0)
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		mode = MODE_INDIVIDUAL;
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (!de::inRange(selBR + selDR, 0, 31))
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		mode = MODE_T;
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (!de::inRange(selBG + selDG, 0, 31))
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		mode = MODE_H;
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (!de::inRange(selBB + selDB, 0, 31))
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		mode = MODE_PLANAR;
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		mode = MODE_DIFFERENTIAL;
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (mode == MODE_INDIVIDUAL || mode == MODE_DIFFERENTIAL)
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Individual and differential modes have some steps in common, handle them here.
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const int modifierTable[8][4] =
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		//	  00   01   10    11
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{  2,   8,  -2,   -8 },
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{  5,  17,  -5,  -17 },
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{  9,  29,  -9,  -29 },
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 13,  42, -13,  -42 },
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 18,  60, -18,  -60 },
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 24,  80, -24,  -80 },
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 33, 106, -33, -106 },
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ 47, 183, -47, -183 }
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		};
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		flipBit		= (int)getBit(src, 32);
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint32	table[2]	= { getBits(src, 37, 39), getBits(src, 34, 36) };
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8			baseR[2];
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8			baseG[2];
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8			baseB[2];
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (mode == MODE_INDIVIDUAL)
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Individual mode, initial values.
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseR[0] = extend4To8((deUint8)getBits(src, 60, 63));
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseR[1] = extend4To8((deUint8)getBits(src, 56, 59));
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseG[0] = extend4To8((deUint8)getBits(src, 52, 55));
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseG[1] = extend4To8((deUint8)getBits(src, 48, 51));
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseB[0] = extend4To8((deUint8)getBits(src, 44, 47));
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseB[1] = extend4To8((deUint8)getBits(src, 40, 43));
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Differential mode, initial values.
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseR[0] = extend5To8(selBR);
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseG[0] = extend5To8(selBG);
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseB[0] = extend5To8(selBB);
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseR[1] = extend5To8((deUint8)(selBR + selDR));
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseG[1] = extend5To8((deUint8)(selBG + selDG));
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseB[1] = extend5To8((deUint8)(selBB + selDB));
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Write final pixels for individual or differential mode.
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int pixelNdx = 0; pixelNdx < ETC2_BLOCK_HEIGHT*ETC2_BLOCK_WIDTH; pixelNdx++)
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		x				= pixelNdx / ETC2_BLOCK_HEIGHT;
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		y				= pixelNdx % ETC2_BLOCK_HEIGHT;
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		dstOffset		= (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		subBlock		= ((flipBit ? y : x) >= 2) ? 1 : 0;
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	tableNdx		= table[subBlock];
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	modifierNdx		= (getBit(src, 16+pixelNdx) << 1) | getBit(src, pixelNdx);
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		alphaDstOffset	= (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_A8; // Only needed for PUNCHTHROUGH version.
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// If doing PUNCHTHROUGH version (alphaMode), opaque bit may affect colors.
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (alphaMode && diffOpaqueBit == 0 && modifierNdx == 2)
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				dst[dstOffset+0]			= 0;
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				dst[dstOffset+1]			= 0;
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				dst[dstOffset+2]			= 0;
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				alphaDst[alphaDstOffset]	= 0;
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int modifier;
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// PUNCHTHROUGH version and opaque bit may also affect modifiers.
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (alphaMode && diffOpaqueBit == 0 && (modifierNdx == 0 || modifierNdx == 2))
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					modifier = 0;
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					modifier = modifierTable[tableNdx][modifierNdx];
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				dst[dstOffset+0] = (deUint8)deClamp32((int)baseR[subBlock] + modifier, 0, 255);
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				dst[dstOffset+1] = (deUint8)deClamp32((int)baseG[subBlock] + modifier, 0, 255);
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				dst[dstOffset+2] = (deUint8)deClamp32((int)baseB[subBlock] + modifier, 0, 255);
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (alphaMode)
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					alphaDst[alphaDstOffset] = 255;
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (mode == MODE_T || mode == MODE_H)
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// T and H modes have some steps in common, handle them here.
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		static const int distTable[8] = { 3, 6, 11, 16, 23, 32, 41, 64 };
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8 paintR[4];
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8 paintG[4];
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deUint8 paintB[4];
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (mode == MODE_T)
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// T mode, calculate paint values.
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8	R1a			= (deUint8)getBits(src, 59, 60);
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8	R1b			= (deUint8)getBits(src, 56, 57);
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8	G1			= (deUint8)getBits(src, 52, 55);
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8	B1			= (deUint8)getBits(src, 48, 51);
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8	R2			= (deUint8)getBits(src, 44, 47);
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8	G2			= (deUint8)getBits(src, 40, 43);
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8	B2			= (deUint8)getBits(src, 36, 39);
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	distNdx		= (getBits(src, 34, 35) << 1) | getBit(src, 32);
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		dist		= distTable[distNdx];
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintR[0] = extend4To8((R1a << 2) | R1b);
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintG[0] = extend4To8(G1);
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintB[0] = extend4To8(B1);
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintR[2] = extend4To8(R2);
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintG[2] = extend4To8(G2);
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintB[2] = extend4To8(B2);
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintR[1] = (deUint8)deClamp32((int)paintR[2] + dist, 0, 255);
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintG[1] = (deUint8)deClamp32((int)paintG[2] + dist, 0, 255);
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintB[1] = (deUint8)deClamp32((int)paintB[2] + dist, 0, 255);
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintR[3] = (deUint8)deClamp32((int)paintR[2] - dist, 0, 255);
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintG[3] = (deUint8)deClamp32((int)paintG[2] - dist, 0, 255);
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintB[3] = (deUint8)deClamp32((int)paintB[2] - dist, 0, 255);
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// H mode, calculate paint values.
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8	R1		= (deUint8)getBits(src, 59, 62);
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8	G1a		= (deUint8)getBits(src, 56, 58);
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8	G1b		= (deUint8)getBit(src, 52);
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8	B1a		= (deUint8)getBit(src, 51);
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8	B1b		= (deUint8)getBits(src, 47, 49);
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8	R2		= (deUint8)getBits(src, 43, 46);
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8	G2		= (deUint8)getBits(src, 39, 42);
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint8	B2		= (deUint8)getBits(src, 35, 38);
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint8			baseR[2];
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint8			baseG[2];
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint8			baseB[2];
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32		baseValue[2];
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint32		distNdx;
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int				dist;
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseR[0]		= extend4To8(R1);
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseG[0]		= extend4To8((G1a << 1) | G1b);
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseB[0]		= extend4To8((B1a << 3) | B1b);
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseR[1]		= extend4To8(R2);
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseG[1]		= extend4To8(G2);
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseB[1]		= extend4To8(B2);
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseValue[0]	= (((deUint32)baseR[0]) << 16) | (((deUint32)baseG[0]) << 8) | baseB[0];
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseValue[1]	= (((deUint32)baseR[1]) << 16) | (((deUint32)baseG[1]) << 8) | baseB[1];
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			distNdx			= (getBit(src, 34) << 2) | (getBit(src, 32) << 1) | (deUint32)(baseValue[0] >= baseValue[1]);
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dist			= distTable[distNdx];
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintR[0]		= (deUint8)deClamp32((int)baseR[0] + dist, 0, 255);
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintG[0]		= (deUint8)deClamp32((int)baseG[0] + dist, 0, 255);
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintB[0]		= (deUint8)deClamp32((int)baseB[0] + dist, 0, 255);
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintR[1]		= (deUint8)deClamp32((int)baseR[0] - dist, 0, 255);
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintG[1]		= (deUint8)deClamp32((int)baseG[0] - dist, 0, 255);
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintB[1]		= (deUint8)deClamp32((int)baseB[0] - dist, 0, 255);
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintR[2]		= (deUint8)deClamp32((int)baseR[1] + dist, 0, 255);
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintG[2]		= (deUint8)deClamp32((int)baseG[1] + dist, 0, 255);
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintB[2]		= (deUint8)deClamp32((int)baseB[1] + dist, 0, 255);
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintR[3]		= (deUint8)deClamp32((int)baseR[1] - dist, 0, 255);
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintG[3]		= (deUint8)deClamp32((int)baseG[1] - dist, 0, 255);
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			paintB[3]		= (deUint8)deClamp32((int)baseB[1] - dist, 0, 255);
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Write final pixels for T or H mode.
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int pixelNdx = 0; pixelNdx < ETC2_BLOCK_HEIGHT*ETC2_BLOCK_WIDTH; pixelNdx++)
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		x				= pixelNdx / ETC2_BLOCK_HEIGHT;
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		y				= pixelNdx % ETC2_BLOCK_HEIGHT;
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		dstOffset		= (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint32	paintNdx		= (getBit(src, 16+pixelNdx) << 1) | getBit(src, pixelNdx);
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int		alphaDstOffset	= (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_A8; // Only needed for PUNCHTHROUGH version.
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (alphaMode && diffOpaqueBit == 0 && paintNdx == 2)
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				dst[dstOffset+0]			= 0;
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				dst[dstOffset+1]			= 0;
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				dst[dstOffset+2]			= 0;
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				alphaDst[alphaDstOffset]	= 0;
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				dst[dstOffset+0] = (deUint8)deClamp32((int)paintR[paintNdx], 0, 255);
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				dst[dstOffset+1] = (deUint8)deClamp32((int)paintG[paintNdx], 0, 255);
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				dst[dstOffset+2] = (deUint8)deClamp32((int)paintB[paintNdx], 0, 255);
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (alphaMode)
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					alphaDst[alphaDstOffset] = 255;
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Planar mode.
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8 GO1	= (deUint8)getBit(src, 56);
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8 GO2	= (deUint8)getBits(src, 49, 54);
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8 BO1	= (deUint8)getBit(src, 48);
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8 BO2	= (deUint8)getBits(src, 43, 44);
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8 BO3	= (deUint8)getBits(src, 39, 41);
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8 RH1	= (deUint8)getBits(src, 34, 38);
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8 RH2	= (deUint8)getBit(src, 32);
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8 RO	= extend6To8((deUint8)getBits(src, 57, 62));
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8 GO	= extend7To8((GO1 << 6) | GO2);
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8 BO	= extend6To8((BO1 << 5) | (BO2 << 3) | BO3);
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8 RH	= extend6To8((RH1 << 1) | RH2);
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8 GH	= extend7To8((deUint8)getBits(src, 25, 31));
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8 BH	= extend6To8((deUint8)getBits(src, 19, 24));
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8 RV	= extend6To8((deUint8)getBits(src, 13, 18));
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8 GV	= extend7To8((deUint8)getBits(src, 6, 12));
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint8 BV	= extend6To8((deUint8)getBits(src, 0, 5));
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Write final pixels for planar mode.
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int y = 0; y < 4; y++)
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int x = 0; x < 4; x++)
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int dstOffset			= (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int unclampedR		= (x * ((int)RH-(int)RO) + y * ((int)RV-(int)RO) + 4*(int)RO + 2) >> 2;
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int unclampedG		= (x * ((int)GH-(int)GO) + y * ((int)GV-(int)GO) + 4*(int)GO + 2) >> 2;
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int unclampedB		= (x * ((int)BH-(int)BO) + y * ((int)BV-(int)BO) + 4*(int)BO + 2) >> 2;
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const int alphaDstOffset	= (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_A8; // Only needed for PUNCHTHROUGH version.
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				dst[dstOffset+0] = (deUint8)deClamp32(unclampedR, 0, 255);
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				dst[dstOffset+1] = (deUint8)deClamp32(unclampedG, 0, 255);
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				dst[dstOffset+2] = (deUint8)deClamp32(unclampedB, 0, 255);
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (alphaMode)
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					alphaDst[alphaDstOffset] = 255;
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void decompressEAC8Block (deUint8 dst[ETC2_UNCOMPRESSED_BLOCK_SIZE_A8], deUint64 src)
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int modifierTable[16][8] =
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-3,  -6,  -9, -15,  2,  5,  8, 14},
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-3,  -7, -10, -13,  2,  6,  9, 12},
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-2,  -5,  -8, -13,  1,  4,  7, 12},
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-2,  -4,  -6, -13,  1,  3,  5, 12},
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-3,  -6,  -8, -12,  2,  5,  7, 11},
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-3,  -7,  -9, -11,  2,  6,  8, 10},
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-4,  -7,  -8, -11,  3,  6,  7, 10},
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-3,  -5,  -8, -11,  2,  4,  7, 10},
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-2,  -6,  -8, -10,  1,  5,  7,  9},
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-2,  -5,  -8, -10,  1,  4,  7,  9},
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-2,  -4,  -8, -10,  1,  3,  7,  9},
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-2,  -5,  -7, -10,  1,  4,  6,  9},
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-3,  -4,  -7, -10,  2,  3,  6,  9},
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-1,  -2,  -3, -10,  0,  1,  2,  9},
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-4,  -6,  -8,  -9,  3,  5,  7,  8},
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-3,  -5,  -7,  -9,  2,  4,  6,  8}
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint8	baseCodeword	= (deUint8)getBits(src, 56, 63);
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint8	multiplier		= (deUint8)getBits(src, 52, 55);
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	tableNdx		= getBits(src, 48, 51);
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int pixelNdx = 0; pixelNdx < ETC2_BLOCK_HEIGHT*ETC2_BLOCK_WIDTH; pixelNdx++)
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		x				= pixelNdx / ETC2_BLOCK_HEIGHT;
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		y				= pixelNdx % ETC2_BLOCK_HEIGHT;
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		dstOffset		= (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_A8;
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		pixelBitNdx		= 45 - 3*pixelNdx;
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint32	modifierNdx		= (getBit(src, pixelBitNdx + 2) << 2) | (getBit(src, pixelBitNdx + 1) << 1) | getBit(src, pixelBitNdx);
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		modifier		= modifierTable[tableNdx][modifierNdx];
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst[dstOffset] = (deUint8)deClamp32((int)baseCodeword + (int)multiplier*modifier, 0, 255);
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void decompressEAC11Block (deUint8 dst[ETC2_UNCOMPRESSED_BLOCK_SIZE_R11], deUint64 src, bool signedMode)
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const int modifierTable[16][8] =
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-3,  -6,  -9, -15,  2,  5,  8, 14},
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-3,  -7, -10, -13,  2,  6,  9, 12},
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-2,  -5,  -8, -13,  1,  4,  7, 12},
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-2,  -4,  -6, -13,  1,  3,  5, 12},
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-3,  -6,  -8, -12,  2,  5,  7, 11},
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-3,  -7,  -9, -11,  2,  6,  8, 10},
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-4,  -7,  -8, -11,  3,  6,  7, 10},
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-3,  -5,  -8, -11,  2,  4,  7, 10},
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-2,  -6,  -8, -10,  1,  5,  7,  9},
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-2,  -5,  -8, -10,  1,  4,  7,  9},
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-2,  -4,  -8, -10,  1,  3,  7,  9},
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-2,  -5,  -7, -10,  1,  4,  6,  9},
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-3,  -4,  -7, -10,  2,  3,  6,  9},
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-1,  -2,  -3, -10,  0,  1,  2,  9},
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-4,  -6,  -8,  -9,  3,  5,  7,  8},
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{-3,  -5,  -7,  -9,  2,  4,  6,  8}
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deInt32 multiplier	= (deInt32)getBits(src, 52, 55);
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deInt32 tableNdx		= (deInt32)getBits(src, 48, 51);
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deInt32 baseCodeword		= (deInt32)getBits(src, 56, 63);
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (signedMode)
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (baseCodeword > 127)
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseCodeword -= 256;
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (baseCodeword == -128)
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			baseCodeword = -127;
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int pixelNdx = 0; pixelNdx < ETC2_BLOCK_HEIGHT*ETC2_BLOCK_WIDTH; pixelNdx++)
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		x				= pixelNdx / ETC2_BLOCK_HEIGHT;
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		y				= pixelNdx % ETC2_BLOCK_HEIGHT;
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		dstOffset		= (y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_R11;
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		pixelBitNdx		= 45 - 3*pixelNdx;
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const deUint32	modifierNdx		= (getBit(src, pixelBitNdx + 2) << 2) | (getBit(src, pixelBitNdx + 1) << 1) | getBit(src, pixelBitNdx);
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		modifier		= modifierTable[tableNdx][modifierNdx];
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (signedMode)
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (multiplier != 0)
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				*(deInt16*)&dst[dstOffset] = (deInt16)deClamp32(baseCodeword*8 + multiplier*modifier*8, -1023, 1023);
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				*(deInt16*)&dst[dstOffset] = (deInt16)deClamp32(baseCodeword*8 + modifier, -1023, 1023);
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (multiplier != 0)
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				*(deUint16*)&dst[dstOffset] = (deUint16)deClamp32(baseCodeword*8 + 4 + multiplier*modifier*8, 0, 2047);
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				*(deUint16*)&dst[dstOffset] = (deUint16)deClamp32(baseCodeword*8 + 4 + modifier, 0, 2047);
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // EtcDecompressInternal
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void decompressETC1 (const tcu::PixelBufferAccess& dst, int width, int height, const deUint8* src)
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace EtcDecompressInternal;
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dst.getWidth() == width && dst.getHeight() == height && dst.getDepth() == 1);
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dst.getFormat() == TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8));
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		numBlocksX		= divRoundUp(width, 4);
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		numBlocksY		= divRoundUp(height, 4);
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint8* const	dstPtr			= (deUint8*)dst.getDataPtr();
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		dstRowPitch		= dst.getRowPitch();
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		dstPixelSize	= ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int blockY = 0; blockY < numBlocksY; blockY++)
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int blockX = 0; blockX < numBlocksX; blockX++)
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint64	compressedBlock = get64BitBlock(src, blockY*numBlocksX + blockX);
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint8			uncompressedBlock[ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8];
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Decompress.
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			decompressETC1Block(uncompressedBlock, compressedBlock);
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Write to dst.
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int baseX = blockX*ETC2_BLOCK_WIDTH;
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int baseY = blockY*ETC2_BLOCK_HEIGHT;
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int y = 0; y < de::min((int)ETC2_BLOCK_HEIGHT, height-baseY); y++)
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int x = 0; x < de::min((int)ETC2_BLOCK_WIDTH, width-baseX); x++)
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint8* const	srcPixel = &uncompressedBlock[(y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8];
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					deUint8* const			dstPixel = dstPtr + (baseY+y)*dstRowPitch + (baseX+x)*dstPixelSize;
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_STATIC_ASSERT(ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8 == 3);
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					dstPixel[0] = srcPixel[0];
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					dstPixel[1] = srcPixel[1];
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					dstPixel[2] = srcPixel[2];
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void decompressETC2 (const tcu::PixelBufferAccess& dst, int width, int height, const deUint8* src)
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace EtcDecompressInternal;
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		numBlocksX		= divRoundUp(width, 4);
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		numBlocksY		= divRoundUp(height, 4);
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint8* const	dstPtr			= (deUint8*)dst.getDataPtr();
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		dstRowPitch		= dst.getRowPitch();
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		dstPixelSize	= ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8;
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int blockY = 0; blockY < numBlocksY; blockY++)
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int blockX = 0; blockX < numBlocksX; blockX++)
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint64	compressedBlock = get64BitBlock(src, blockY*numBlocksX + blockX);
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint8			uncompressedBlock[ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8];
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Decompress.
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			decompressETC2Block(uncompressedBlock, compressedBlock, NULL, false);
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Write to dst.
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int baseX = blockX*ETC2_BLOCK_WIDTH;
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int baseY = blockY*ETC2_BLOCK_HEIGHT;
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (int y = 0; y < de::min((int)ETC2_BLOCK_HEIGHT, height-baseY); y++)
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				for (int x = 0; x < de::min((int)ETC2_BLOCK_WIDTH, width-baseX); x++)
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					const deUint8* const	srcPixel = &uncompressedBlock[(y*ETC2_BLOCK_WIDTH + x)*ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8];
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					deUint8* const			dstPixel = dstPtr + (baseY+y)*dstRowPitch + (baseX+x)*dstPixelSize;
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_STATIC_ASSERT(ETC2_UNCOMPRESSED_PIXEL_SIZE_RGB8 == 3);
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					dstPixel[0] = srcPixel[0];
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					dstPixel[1] = srcPixel[1];
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					dstPixel[2] = srcPixel[2];
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void decompressETC2_EAC_RGBA8 (const tcu::PixelBufferAccess& dst, int width, int height, const deUint8* src)
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	using namespace EtcDecompressInternal;
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		numBlocksX		= divRoundUp(width, 4);
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		numBlocksY		= divRoundUp(height, 4);
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint8* const	dstPtr			= (deUint8*)dst.getDataPtr();
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		dstRowPitch		= dst.getRowPitch();
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int		dstPixelSize	= ETC2_UNCOMPRESSED_PIXEL_SIZE_RGBA8;
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int blockY = 0; blockY < numBlocksY; blockY++)
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int blockX = 0; blockX < numBlocksX; blockX++)
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint64	compressedBlockAlpha	= get128BitBlockStart(src, blockY*numBlocksX + blockX);
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint64	compressedBlockRGB		= get128BitBlockEnd(src, blockY*numBlocksX + blockX);
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint8			uncompressedBlockAlpha[ETC2_UNCOMPRESSED_BLOCK_SIZE_A8];
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint8			uncompressedBlockRGB[ETC2_UNCOMPRESSED_BLOCK_SIZE_RGB8];
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Decompress.
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			decompressETC2Block(uncompressedBlockRGB, compressedBlockRGB, NULL, false);
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			decompressEAC8Block(uncompressedBlockAlpha, compressedBlockAlpha);
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Write to dst.
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int baseX = blockX*ETC2_BLOCK_WIDTH;
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const int baseY = blockY*ETC2_BLOCK_HEIGHT;
9443c827367444ee418f129b2c238299f49d3264554Ja