From 1220e7fe54b61656c5bf6ee6c39a1815a9ca497f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Tue, 22 May 2018 18:09:37 -0700 Subject: [PATCH] BC7 decoding WIP. --- src/image.cpp | 494 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 483 insertions(+), 11 deletions(-) diff --git a/src/image.cpp b/src/image.cpp index 29a7236..4f9a72c 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -976,6 +976,20 @@ namespace bimg if (NULL == pack || NULL == unpack) { + switch (_dstFormat) + { + case TextureFormat::RGBA8: + imageDecodeToRgba8(_dst, _src, _width, _height, _width*4, _srcFormat); + return true; + + case TextureFormat::BGRA8: + imageDecodeToBgra8(_dst, _src, _width, _height, _width*4, _srcFormat); + return true; + + default: + break; + } + return false; } @@ -1240,19 +1254,460 @@ namespace bimg } } - static const int32_t s_etc1Mod[8][4] = - { - { 2, 8, -2, -8}, - { 5, 17, -5, -17}, - { 9, 29, -9, -29}, - { 13, 42, -13, -42}, - { 18, 60, -18, -60}, - { 24, 80, -24, -80}, - { 33, 106, -33, -106}, - { 47, 183, -47, -183}, + // BC6H, BC7 + // + // Reference: + // + // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression_bptc.txt + // https://msdn.microsoft.com/en-us/library/windows/desktop/hh308952(v=vs.85).aspx + + static const uint16_t s_bctcP2[] = + { // 3210 0000000000 1111111111 2222222222 3333333333 + 0xcccc, // 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 + 0x8888, // 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 + 0xeeee, // 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 + 0xecc8, // 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1 + 0xc880, // 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1 + 0xfeec, // 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 + 0xfec8, // 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 + 0xec80, // 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1 + 0xc800, // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1 + 0xffec, // 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + 0xfe80, // 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1 + 0xe800, // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1 + 0xffe8, // 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + 0xff00, // 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 + 0xfff0, // 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + 0xf000, // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 + 0xf710, // 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1 + 0x008e, // 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 + 0x7100, // 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0 + 0x08ce, // 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0 + 0x008c, // 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 + 0x7310, // 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0 + 0x3100, // 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 + 0x8cce, // 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1 + 0x088c, // 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 + 0x3110, // 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0 + 0x6666, // 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0 + 0x366c, // 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0 + 0x17e8, // 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0 + 0x0ff0, // 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 + 0x718e, // 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0 + 0x399c, // 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0 + 0xaaaa, // 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + 0xf0f0, // 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 + 0x5a5a, // 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0 + 0x33cc, // 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0 + 0x3c3c, // 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0 + 0x55aa, // 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0 + 0x9696, // 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1 + 0xa55a, // 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1 + 0x73ce, // 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0 + 0x13c8, // 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0 + 0x324c, // 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 + 0x3bdc, // 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0 + 0x6996, // 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 + 0xc33c, // 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1 + 0x9966, // 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1 + 0x0660, // 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 + 0x0272, // 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 + 0x04e4, // 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0 + 0x4e40, // 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0 + 0x2720, // 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0 + 0xc936, // 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 + 0x936c, // 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1 + 0x39c6, // 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0 + 0x639c, // 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0 + 0x9336, // 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1 + 0x9cc6, // 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1 + 0x817e, // 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 + 0xe718, // 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1 + 0xccf0, // 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 + 0x0fcc, // 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 + 0x7744, // 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0 + 0xee22, // 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1 }; - static const uint8_t s_etc2Mod[8] = { 3, 6, 11, 16, 23, 32, 41, 64 }; + static const uint32_t s_bctcP3[] = + { // 76543210 0000 1111 2222 3333 4444 5555 6666 7777 + 0xaa685050, // 0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 1, 2, 2, 2, 2 + 0x6a5a5040, // 0, 0, 0, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 2, 1 + 0x5a5a4200, // 0, 0, 0, 0, 2, 0, 0, 1, 2, 2, 1, 1, 2, 2, 1, 1 + 0x5450a0a8, // 0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 1, 0, 1, 1, 1 + 0xa5a50000, // 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2 + 0xa0a05050, // 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 2, 2 + 0x5555a0a0, // 0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 + 0x5a5a5050, // 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1 + 0xaa550000, // 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2 + 0xaa555500, // 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2 + 0xaaaa5500, // 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2 + 0x90909090, // 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2 + 0x94949494, // 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2, 0, 1, 1, 2 + 0xa4a4a4a4, // 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2 + 0xa9a59450, // 0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2 + 0x2a0a4250, // 0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0, 2, 2, 2, 0 + 0xa5945040, // 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 2, 1, 1, 2, 2 + 0x0a425054, // 0, 1, 1, 1, 0, 0, 1, 1, 2, 0, 0, 1, 2, 2, 0, 0 + 0xa5a5a500, // 0, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2 + 0x55a0a0a0, // 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1 + 0xa8a85454, // 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2, 0, 2, 2, 2 + 0x6a6a4040, // 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, 2, 1, 2, 2, 2, 1 + 0xa4a45000, // 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2 + 0x1a1a0500, // 0, 0, 0, 0, 1, 1, 0, 0, 2, 2, 1, 0, 2, 2, 1, 0 + 0x0050a4a4, // 0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1, 0, 0, 0, 0 + 0xaaa59090, // 0, 0, 1, 2, 0, 0, 1, 2, 1, 1, 2, 2, 2, 2, 2, 2 + 0x14696914, // 0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1, 0, 1, 1, 0 + 0x69691400, // 0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 1, 1, 2, 2, 1 + 0xa08585a0, // 0, 0, 2, 2, 1, 1, 0, 2, 1, 1, 0, 2, 0, 0, 2, 2 + 0xaa821414, // 0, 1, 1, 0, 0, 1, 1, 0, 2, 0, 0, 2, 2, 2, 2, 2 + 0x50a4a450, // 0, 0, 1, 1, 0, 1, 2, 2, 0, 1, 2, 2, 0, 0, 1, 1 + 0x6a5a0200, // 0, 0, 0, 0, 2, 0, 0, 0, 2, 2, 1, 1, 2, 2, 2, 1 + 0xa9a58000, // 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 2, 2, 2 + 0x5090a0a8, // 0, 2, 2, 2, 0, 0, 2, 2, 0, 0, 1, 2, 0, 0, 1, 1 + 0xa8a09050, // 0, 0, 1, 1, 0, 0, 1, 2, 0, 0, 2, 2, 0, 2, 2, 2 + 0x24242424, // 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0 + 0x00aa5500, // 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0 + 0x24924924, // 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0 + 0x24499224, // 0, 1, 2, 0, 2, 0, 1, 2, 1, 2, 0, 1, 0, 1, 2, 0 + 0x50a50a50, // 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2, 0, 0, 1, 1 + 0x500aa550, // 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 1, 1 + 0xaaaa4444, // 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2 + 0x66660000, // 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1 + 0xa5a0a5a0, // 0, 0, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2, 1, 1, 2, 2 + 0x50a050a0, // 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 1, 1 + 0x69286928, // 0, 2, 2, 0, 1, 2, 2, 1, 0, 2, 2, 0, 1, 2, 2, 1 + 0x44aaaa44, // 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 0, 1 + 0x66666600, // 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1 + 0xaa444444, // 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 2, 2 + 0x54a854a8, // 0, 2, 2, 2, 0, 1, 1, 1, 0, 2, 2, 2, 0, 1, 1, 1 + 0x95809580, // 0, 0, 0, 2, 1, 1, 1, 2, 0, 0, 0, 2, 1, 1, 1, 2 + 0x96969600, // 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2 + 0xa85454a8, // 0, 2, 2, 2, 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2 + 0x80959580, // 0, 0, 0, 2, 1, 1, 1, 2, 1, 1, 1, 2, 0, 0, 0, 2 + 0xaa141414, // 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2 + 0x96960000, // 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 1, 2 + 0xaaaa1414, // 0, 1, 1, 0, 0, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2 + 0xa05050a0, // 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 2, 2 + 0xa0a5a5a0, // 0, 0, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 0, 0, 2, 2 + 0x96000000, // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2 + 0x40804080, // 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1 + 0xa9a8a9a8, // 0, 2, 2, 2, 1, 2, 2, 2, 0, 2, 2, 2, 1, 2, 2, 2 + 0xaaaaaa44, // 0, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 + 0x2a4a5254, // 0, 1, 1, 1, 2, 0, 1, 1, 2, 2, 0, 1, 2, 2, 2, 0 + }; + + static const uint8_t s_bctcA2[] = + { + 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, + 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, + }; + + static const uint8_t s_bctcA3[2][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, + 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, + }, + { + 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, + 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, + }, + }; + + static const uint8_t s_bctcFactors[3][18] = + { + { 0, 21, 43, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 9, 18, 27, 37, 46, 55, 64, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 }, + }; + + struct BctcModeInfo + { + uint8_t numSubsets; + uint8_t partitionBits; + uint8_t rotationBits; + uint8_t indexSelectionBits; + uint8_t colorBits; + uint8_t alphaBits; + uint8_t endpointPBits; + uint8_t sharedPBits; + uint8_t indexBits[2]; + }; + + static const BctcModeInfo s_bctcModeInfo[] = + { // +---------------------------- num subsets + // | +------------------------- partition bits + // | | +---------------------- rotation bits + // | | | +------------------- index selection bits + // | | | | +---------------- color bits + // | | | | | +------------- alpha bits + // | | | | | | +---------- endpoint P-bits + // | | | | | | | +------- shared P-bits + // | | | | | | | | +-- 2x index bits + { 3, 4, 0, 0, 4, 0, 1, 0, { 3, 0 } }, // 0 + { 2, 6, 0, 0, 6, 0, 0, 1, { 3, 0 } }, // 1 + { 3, 6, 0, 0, 5, 0, 0, 0, { 2, 0 } }, // 2 + { 2, 6, 0, 0, 7, 0, 1, 0, { 2, 0 } }, // 3 + { 1, 0, 2, 1, 5, 6, 0, 0, { 2, 3 } }, // 4 + { 1, 0, 2, 0, 7, 8, 0, 0, { 2, 2 } }, // 5 + { 1, 0, 0, 0, 7, 7, 1, 0, { 4, 0 } }, // 6 + { 2, 6, 0, 0, 5, 5, 1, 0, { 2, 0 } }, // 7 + }; + + struct BitReader + { + BitReader(const uint8_t* _data, uint16_t _bitPos = 0) + : m_data(_data) + , m_bitPos(_bitPos) + { + } + + uint8_t read(uint8_t _numBits) + { + const uint16_t pos = m_bitPos / 8; + const uint16_t shift = m_bitPos & 7; + const uint16_t data = *( (uint16_t*)&m_data[pos]); + m_bitPos += _numBits; + return uint8_t( (data >> shift) & ( (1 << _numBits)-1) ); + } + + uint8_t peek(uint16_t _offset, uint8_t _numBits) + { + const uint16_t bitPos = m_bitPos + _offset; + const uint16_t pos = bitPos / 8; + const uint16_t shift = bitPos & 7; + const uint16_t data = *( (uint16_t*)&m_data[pos]); + return uint8_t( (data >> shift) & ( (1 << _numBits)-1) ); + } + + const uint8_t* m_data; + uint16_t m_bitPos; + }; + + void decodeBlockBc6(float _dst[16*4], const uint8_t _src[16]) + { + BX_UNUSED(_dst, _src); + } + + void decodeBlockBc7(uint8_t _dst[16*4], const uint8_t _src[16]) + { + BitReader bit(_src); + + uint8_t mode = 0; + for (; mode < 8 && 0 == bit.read(1); ++mode) + { + } + + if (mode == 8) + { + bx::memSet(_dst, 0, 16*4); + return; + } + + const BctcModeInfo& mi = s_bctcModeInfo[mode]; + const uint8_t modePBits = 0 != mi.endpointPBits + ? mi.endpointPBits + : mi.sharedPBits + ; + + const uint8_t partitionSetIdx = bit.read(mi.partitionBits); + const uint8_t rotationMode = bit.read(mi.rotationBits); + const uint8_t indexSelectionMode = bit.read(mi.indexSelectionBits); + + uint8_t epR[6]; + uint8_t epG[6]; + uint8_t epB[6]; + uint8_t epA[6]; + + for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) + { + epR[ii*2+0] = bit.read(mi.colorBits) << modePBits; + epR[ii*2+1] = bit.read(mi.colorBits) << modePBits; + } + + for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) + { + epG[ii*2+0] = bit.read(mi.colorBits) << modePBits; + epG[ii*2+1] = bit.read(mi.colorBits) << modePBits; + } + + for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) + { + epB[ii*2+0] = bit.read(mi.colorBits) << modePBits; + epB[ii*2+1] = bit.read(mi.colorBits) << modePBits; + } + + if (mi.alphaBits) + { + for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) + { + epA[ii*2+0] = bit.read(mi.alphaBits) << modePBits; + epA[ii*2+1] = bit.read(mi.alphaBits) << modePBits; + } + } + else + { + bx::memSet(epA, 0xff, 6); + } + + if (0 != modePBits) + { + for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) + { + const uint8_t pda = bit.read(modePBits); + const uint8_t pdb = 0 != mi.sharedPBits ? bit.read(modePBits) : pda; + + epR[ii*2+0] |= pda; + epR[ii*2+1] |= pdb; + epG[ii*2+0] |= pda; + epG[ii*2+1] |= pdb; + epB[ii*2+0] |= pda; + epB[ii*2+1] |= pdb; + epA[ii*2+0] |= pda; + epA[ii*2+1] |= pdb; + } + } + + const uint8_t colorBits = mi.colorBits + modePBits; + + for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) + { + epR[ii*2+0] = bitRangeConvert(epR[ii*2+0], colorBits, 8); + epR[ii*2+1] = bitRangeConvert(epR[ii*2+1], colorBits, 8); + epG[ii*2+0] = bitRangeConvert(epG[ii*2+0], colorBits, 8); + epG[ii*2+1] = bitRangeConvert(epG[ii*2+1], colorBits, 8); + epB[ii*2+0] = bitRangeConvert(epB[ii*2+0], colorBits, 8); + epB[ii*2+1] = bitRangeConvert(epB[ii*2+1], colorBits, 8); + } + + if (mi.alphaBits) + { + const uint8_t alphaBits = mi.alphaBits + modePBits; + + for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) + { + epA[ii*2+0] = bitRangeConvert(epA[ii*2+0], alphaBits, 8); + epA[ii*2+1] = bitRangeConvert(epA[ii*2+1], alphaBits, 8); + } + } + + const bool hasIndexBits1 = 0 != mi.indexBits[1]; + + const uint8_t* factors[] = + { + s_bctcFactors[mi.indexBits[0]-2], + hasIndexBits1 ? s_bctcFactors[mi.indexBits[1]-2] : s_bctcFactors[0], + }; + + uint16_t offset[2] = + { + 0, + uint16_t(mi.numSubsets*(16*mi.indexBits[0]-1) ), + }; + + for (uint8_t yy = 0; yy < 4; ++yy) + { + for (uint8_t xx = 0; xx < 4; ++xx) + { + const uint8_t idx = yy*4+xx; + + uint8_t subsetIndex = 0; + uint8_t indexAnchor = 0; + switch (mi.numSubsets) + { + case 2: + subsetIndex = (s_bctcP2[partitionSetIdx] >> idx) & 1; + indexAnchor = 0 != subsetIndex ? s_bctcA2[partitionSetIdx] : 0; + break; + + case 3: + subsetIndex = (s_bctcP3[partitionSetIdx] >> (2*idx) ) & 3; + indexAnchor = 0 != subsetIndex ? s_bctcA3[subsetIndex-1][partitionSetIdx] : 0; + break; + + default: + break; + } + + const uint8_t anchor = idx == indexAnchor; + const uint8_t num[2] = + { + uint8_t(mi.indexBits[0] - anchor), + uint8_t(hasIndexBits1 ? mi.indexBits[1] - anchor : 0), + }; + + const uint8_t index[2] = + { + bit.peek(offset[0], num[0]), + hasIndexBits1 ? bit.peek(offset[1], num[1]) : index[0], + }; + + offset[0] += num[0]; + offset[1] += num[1]; + + const uint8_t fc = factors[ indexSelectionMode][index[ indexSelectionMode] ]; + const uint8_t fa = factors[!indexSelectionMode][index[!indexSelectionMode] ]; + + const uint8_t fca = 64 - fc; + const uint8_t fcb = fc; + const uint8_t faa = 64 - fa; + const uint8_t fab = fa; + + subsetIndex *= 2; + uint8_t rr = uint8_t(uint16_t(epR[subsetIndex]*fca + epR[subsetIndex + 1]*fcb + 32) >> 6); + uint8_t gg = uint8_t(uint16_t(epG[subsetIndex]*fca + epG[subsetIndex + 1]*fcb + 32) >> 6); + uint8_t bb = uint8_t(uint16_t(epB[subsetIndex]*fca + epB[subsetIndex + 1]*fcb + 32) >> 6); + uint8_t aa = uint8_t(uint16_t(epA[subsetIndex]*faa + epA[subsetIndex + 1]*fab + 32) >> 6); + + switch (rotationMode) + { + case 1: bx::xchg(aa, rr); break; + case 2: bx::xchg(aa, gg); break; + case 3: bx::xchg(aa, bb); break; + default: break; + }; + + uint8_t* bgra = &_dst[(yy*4+xx)*4]; + bgra[0] = bb; + bgra[1] = gg; + bgra[2] = rr; + bgra[3] = aa; + } + } + } + + static const int32_t s_etc1Mod[8][4] = + { + { 2, 8, -2, -8 }, + { 5, 17, -5, -17 }, + { 9, 29, -9, -29 }, + { 13, 42, -13, -42 }, + { 18, 60, -18, -60 }, + { 24, 80, -24, -80 }, + { 33, 106, -33, -106 }, + { 47, 183, -47, -183 }, + }; + + static const uint8_t s_etc2Mod[] = { 3, 6, 11, 16, 23, 32, 41, 64 }; uint8_t uint8_sat(int32_t _a) { @@ -3034,6 +3489,23 @@ namespace bimg } break; + case TextureFormat::BC7: + for (uint32_t yy = 0; yy < height; ++yy) + { + for (uint32_t xx = 0; xx < width; ++xx) + { + decodeBlockBc7(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); + } + } + break; + case TextureFormat::ETC1: case TextureFormat::ETC2: for (uint32_t yy = 0; yy < height; ++yy)