Browse Source

Merge pull request #60 from attilaz/etc2a_decode

added etc2a decoder
Бранимир Караџић 4 years ago
parent
commit
39c0a7885d
1 changed files with 70 additions and 2 deletions
  1. 70 2
      src/image.cpp

+ 70 - 2
src/image.cpp

@@ -2934,6 +2934,52 @@ namespace bimg
 		}
 	}
 
+	static const int8_t s_etc2aMod[16][8] =
+	{
+		{ -3, -6,  -9, -15, 2, 5, 8, 14 },
+		{ -3, -7, -10, -13, 2, 6, 9, 12 },
+		{ -2, -5,  -8, -13, 1, 4, 7, 12 },
+		{ -2, -4,  -6, -13, 1, 3, 5, 12 },
+		{ -3, -6,  -8, -12, 2, 5, 7, 11 },
+		{ -3, -7,  -9, -11, 2, 6, 8, 10 },
+		{ -4, -7,  -8, -11, 3, 6, 7, 10 },
+		{ -3, -5,  -8, -11, 2, 4, 7, 10 },
+		{ -2, -6,  -8, -10, 1, 5, 7,  9 },
+		{ -2, -5,  -8, -10, 1, 4, 7,  9 },
+		{ -2, -4,  -8, -10, 1, 3, 7,  9 },
+		{ -2, -5,  -7, -10, 1, 4, 6,  9 },
+		{ -3, -4,  -7, -10, 2, 3, 6,  9 },
+		{ -1, -2,  -3, -10, 0, 1, 2,  9 },
+		{ -4, -6,  -8,  -9, 3, 5, 7,  8 },
+		{ -3, -5,  -7,  -9, 2, 4, 6,  8 }
+	};
+
+	void decodeBlockEtc2Alpha(uint8_t _dst[16 * 4], const uint8_t _src[8])
+	{
+		if (!BX_ENABLED(BIMG_DECODE_ETC2))
+		{
+			return;
+		}
+
+		const int32_t bc = _src[0];
+		const int8_t *modTable = s_etc2aMod[_src[1] & 0x0f];
+		const int32_t mult = (_src[1] & 0xf0) >> 4;
+		const uint64_t indices = ((uint64_t)_src[2] << 40)
+			| ((uint64_t)_src[3] << 32)
+			| ((uint64_t)_src[4] << 24)
+			| ((uint64_t)_src[5] << 16)
+			| ((uint64_t)_src[6] << 8)
+			| _src[7];
+
+		for (int ii = 0; ii < 16; ii++) {
+			const uint32_t idx = (ii & 0xc) | ((ii & 0x3) << 4);
+			const  int32_t mod = modTable[(indices >> (45 - ii * 3)) & 0x7];
+
+			_dst[idx + 3] = uint8_satadd(bc, mod*mult);
+		}
+	}
+
+
 	static const uint8_t s_pvrtcFactors[16][4] =
 	{
 		{  4,  4,  4,  4 },
@@ -4544,8 +4590,30 @@ namespace bimg
 			break;
 
 		case TextureFormat::ETC2A:
-			BX_WARN(false, "ETC2A decoder is not implemented.");
-			imageCheckerboard(_dst, _width, _height, 16, UINT32_C(0xff000000), UINT32_C(0xff00ff00) );
+			if (BX_ENABLED(BIMG_DECODE_ETC2))
+			{
+				for (uint32_t yy = 0; yy < height; ++yy)
+				{
+					for (uint32_t xx = 0; xx < width; ++xx)
+					{
+						decodeBlockEtc12(temp, src + 8);
+						decodeBlockEtc2Alpha(temp, src);
+
+						src += 16;
+
+						uint8_t* block = &dst[yy*_dstPitch * 4 + xx * 16];
+						bx::memCopy(&block[0 * _dstPitch], &temp[0], 16);
+						bx::memCopy(&block[1 * _dstPitch], &temp[16], 16);
+						bx::memCopy(&block[2 * _dstPitch], &temp[32], 16);
+						bx::memCopy(&block[3 * _dstPitch], &temp[48], 16);
+					}
+				}
+			}
+			else
+			{
+				BX_WARN(false, "ETC2 decoder is disabled (BIMG_DECODE_ETC2).");
+				imageCheckerboard(_dst, _width, _height, 16, UINT32_C(0xff000000), UINT32_C(0xff00ff00));
+			}
 			break;
 
 		case TextureFormat::ETC2A1: