mirror of
https://github.com/scratchfoundation/bgfx.git
synced 2024-11-25 00:58:30 -05:00
Added ETC2 decoding.
This commit is contained in:
parent
666b431b40
commit
528a725387
1 changed files with 272 additions and 24 deletions
296
src/image.cpp
296
src/image.cpp
|
@ -442,7 +442,7 @@ namespace bgfx
|
|||
}
|
||||
}
|
||||
|
||||
static const int32_t s_mod[8][4] =
|
||||
static const int32_t s_etc1Mod[8][4] =
|
||||
{
|
||||
{ 2, 8, -2, -8},
|
||||
{ 15, 17, -15, -17},
|
||||
|
@ -454,16 +454,248 @@ namespace bgfx
|
|||
{ 47, 183, -47, -183},
|
||||
};
|
||||
|
||||
uint8_t uint8_satadd(int32_t _a, int32_t _b)
|
||||
static const uint8_t s_etc2Mod[8] = { 3, 6, 11, 16, 23, 32, 41, 64 };
|
||||
|
||||
uint8_t uint8_sat(int32_t _a)
|
||||
{
|
||||
using namespace bx;
|
||||
const int32_t add = _a + _b;
|
||||
const uint32_t min = uint32_imin(add, 255);
|
||||
const uint32_t min = uint32_imin(_a, 255);
|
||||
const uint32_t result = uint32_imax(min, 0);
|
||||
return (uint8_t)result;
|
||||
}
|
||||
|
||||
void decodeBlockEtc1(uint8_t _dst[16*4], const uint8_t _src[8])
|
||||
uint8_t uint8_satadd(int32_t _a, int32_t _b)
|
||||
{
|
||||
const int32_t add = _a + _b;
|
||||
return uint8_sat(add);
|
||||
}
|
||||
|
||||
void decodeBlockEtc2ModeT(uint8_t _dst[16*4], const uint8_t _src[8])
|
||||
{
|
||||
uint8_t rgb[16];
|
||||
|
||||
// 0 1 2 3 4 5 6 7
|
||||
// 7654321076543210765432107654321076543210765432107654321076543210
|
||||
// ...rr.rrggggbbbbrrrrggggbbbbDDD.mmmmmmmmmmmmmmmmllllllllllllllll
|
||||
// ^ ^ ^ ^ ^
|
||||
// +-- c0 +-- c1 | +-- msb +-- lsb
|
||||
// +-- dist
|
||||
|
||||
rgb[ 0] = ( (_src[0] >> 1) & 0xc)
|
||||
| (_src[0] & 0x3)
|
||||
;
|
||||
rgb[ 1] = _src[1] >> 4;
|
||||
rgb[ 2] = _src[1] & 0xf;
|
||||
|
||||
rgb[ 8] = _src[2] >> 4;
|
||||
rgb[ 9] = _src[2] & 0xf;
|
||||
rgb[10] = _src[3] >> 4;
|
||||
|
||||
rgb[ 0] = bitRangeConvert(rgb[ 0], 4, 8);
|
||||
rgb[ 1] = bitRangeConvert(rgb[ 1], 4, 8);
|
||||
rgb[ 2] = bitRangeConvert(rgb[ 2], 4, 8);
|
||||
rgb[ 8] = bitRangeConvert(rgb[ 8], 4, 8);
|
||||
rgb[ 9] = bitRangeConvert(rgb[ 9], 4, 8);
|
||||
rgb[10] = bitRangeConvert(rgb[10], 4, 8);
|
||||
|
||||
uint8_t dist = (_src[3] >> 1) & 0x7;
|
||||
int32_t mod = s_etc2Mod[dist];
|
||||
|
||||
rgb[ 4] = uint8_satadd(rgb[ 8], mod);
|
||||
rgb[ 5] = uint8_satadd(rgb[ 9], mod);
|
||||
rgb[ 6] = uint8_satadd(rgb[10], mod);
|
||||
|
||||
rgb[12] = uint8_satadd(rgb[ 8], -mod);
|
||||
rgb[13] = uint8_satadd(rgb[ 9], -mod);
|
||||
rgb[14] = uint8_satadd(rgb[10], -mod);
|
||||
|
||||
uint32_t indexMsb = (_src[4]<<8) | _src[5];
|
||||
uint32_t indexLsb = (_src[6]<<8) | _src[7];
|
||||
|
||||
for (uint32_t ii = 0; ii < 16; ++ii)
|
||||
{
|
||||
const uint32_t idx = (ii&0xc) | ( (ii & 0x3)<<4);
|
||||
const uint32_t lsbi = indexLsb & 1;
|
||||
const uint32_t msbi = (indexMsb & 1)<<1;
|
||||
const uint32_t pal = (lsbi | msbi)<<2;
|
||||
|
||||
_dst[idx + 0] = rgb[pal+2];
|
||||
_dst[idx + 1] = rgb[pal+1];
|
||||
_dst[idx + 2] = rgb[pal+0];
|
||||
_dst[idx + 3] = 255;
|
||||
|
||||
indexLsb >>= 1;
|
||||
indexMsb >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void decodeBlockEtc2ModeH(uint8_t _dst[16*4], const uint8_t _src[8])
|
||||
{
|
||||
uint8_t rgb[16];
|
||||
|
||||
// 0 1 2 3 4 5 6 7
|
||||
// 7654321076543210765432107654321076543210765432107654321076543210
|
||||
// .rrrrggg...gb.bbbrrrrggggbbbbDD.mmmmmmmmmmmmmmmmllllllllllllllll
|
||||
// ^ ^ ^ ^ ^
|
||||
// +-- c0 +-- c1 | +-- msb +-- lsb
|
||||
// +-- dist
|
||||
|
||||
rgb[ 0] = (_src[0] >> 3) & 0xf;
|
||||
rgb[ 1] = ( (_src[0] << 1) & 0xe)
|
||||
| ( (_src[1] >> 4) & 0x1)
|
||||
;
|
||||
rgb[ 2] = (_src[1] & 0x8)
|
||||
| ( (_src[1] << 1) & 0x6)
|
||||
| (_src[2] >> 7)
|
||||
;
|
||||
|
||||
rgb[ 8] = (_src[2] >> 3) & 0xf;
|
||||
rgb[ 9] = ( (_src[2] << 1) & 0xe)
|
||||
| (_src[3] >> 7)
|
||||
;
|
||||
rgb[10] = (_src[2] >> 3) & 0xf;
|
||||
|
||||
rgb[ 0] = bitRangeConvert(rgb[ 0], 4, 8);
|
||||
rgb[ 1] = bitRangeConvert(rgb[ 1], 4, 8);
|
||||
rgb[ 2] = bitRangeConvert(rgb[ 2], 4, 8);
|
||||
rgb[ 8] = bitRangeConvert(rgb[ 8], 4, 8);
|
||||
rgb[ 9] = bitRangeConvert(rgb[ 9], 4, 8);
|
||||
rgb[10] = bitRangeConvert(rgb[10], 4, 8);
|
||||
|
||||
uint32_t col0 = uint32_t(rgb[0]<<16) | uint32_t(rgb[1]<<8) | uint32_t(rgb[ 2]);
|
||||
uint32_t col1 = uint32_t(rgb[8]<<16) | uint32_t(rgb[9]<<8) | uint32_t(rgb[10]);
|
||||
uint8_t dist = (_src[3] & 0x6) | (col0 >= col1);
|
||||
int32_t mod = s_etc2Mod[dist];
|
||||
|
||||
rgb[ 4] = uint8_satadd(rgb[ 0], -mod);
|
||||
rgb[ 5] = uint8_satadd(rgb[ 1], -mod);
|
||||
rgb[ 6] = uint8_satadd(rgb[ 2], -mod);
|
||||
|
||||
rgb[ 0] = uint8_satadd(rgb[ 0], mod);
|
||||
rgb[ 1] = uint8_satadd(rgb[ 1], mod);
|
||||
rgb[ 2] = uint8_satadd(rgb[ 2], mod);
|
||||
|
||||
rgb[12] = uint8_satadd(rgb[ 8], -mod);
|
||||
rgb[13] = uint8_satadd(rgb[ 9], -mod);
|
||||
rgb[14] = uint8_satadd(rgb[10], -mod);
|
||||
|
||||
rgb[ 8] = uint8_satadd(rgb[ 8], mod);
|
||||
rgb[ 9] = uint8_satadd(rgb[ 9], mod);
|
||||
rgb[10] = uint8_satadd(rgb[10], mod);
|
||||
|
||||
uint32_t indexMsb = (_src[4]<<8) | _src[5];
|
||||
uint32_t indexLsb = (_src[6]<<8) | _src[7];
|
||||
|
||||
for (uint32_t ii = 0; ii < 16; ++ii)
|
||||
{
|
||||
const uint32_t idx = (ii&0xc) | ( (ii & 0x3)<<4);
|
||||
const uint32_t lsbi = indexLsb & 1;
|
||||
const uint32_t msbi = (indexMsb & 1)<<1;
|
||||
const uint32_t pal = (lsbi | msbi)<<2;
|
||||
|
||||
_dst[idx + 0] = rgb[pal+2];
|
||||
_dst[idx + 1] = rgb[pal+1];
|
||||
_dst[idx + 2] = rgb[pal+0];
|
||||
_dst[idx + 3] = 255;
|
||||
|
||||
indexLsb >>= 1;
|
||||
indexMsb >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void decodeBlockEtc2ModePlanar(uint8_t _dst[16*4], const uint8_t _src[8])
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7
|
||||
// 7654321076543210765432107654321076543210765432107654321076543210
|
||||
// .rrrrrrg.ggggggb...bb.bbbrrrrr.rgggggggbbbbbbrrrrrrgggggggbbbbbb
|
||||
// ^ ^ ^
|
||||
// +-- c0 +-- cH +-- cV
|
||||
|
||||
uint8_t c0[3];
|
||||
uint8_t cH[3];
|
||||
uint8_t cV[3];
|
||||
|
||||
c0[0] = (_src[0] >> 1) & 0x3f;
|
||||
c0[1] = ( (_src[0] & 1) << 6)
|
||||
| ( (_src[1] >> 1) & 0x3f)
|
||||
;
|
||||
c0[2] = ( (_src[1] & 1) << 5)
|
||||
| ( (_src[2] & 0x18) )
|
||||
| ( (_src[2] << 1) & 6)
|
||||
| ( (_src[3] >> 7) )
|
||||
;
|
||||
|
||||
cH[0] = ( (_src[3] >> 1) & 0x3e)
|
||||
| (_src[3] & 1)
|
||||
;
|
||||
cH[1] = _src[4] >> 1;
|
||||
cH[2] = ( (_src[4] & 1) << 5)
|
||||
| (_src[5] >> 3)
|
||||
;
|
||||
|
||||
cV[0] = ( (_src[5] & 0x7) << 3)
|
||||
| (_src[6] >> 5)
|
||||
;
|
||||
cV[1] = ( (_src[6] & 0x1f) << 2)
|
||||
| (_src[7] >> 5)
|
||||
;
|
||||
cV[2] = _src[8] & 0x3f;
|
||||
|
||||
c0[0] = bitRangeConvert(c0[0], 6, 8);
|
||||
c0[1] = bitRangeConvert(c0[1], 7, 8);
|
||||
c0[2] = bitRangeConvert(c0[2], 6, 8);
|
||||
|
||||
cH[0] = bitRangeConvert(cH[0], 6, 8);
|
||||
cH[1] = bitRangeConvert(cH[1], 7, 8);
|
||||
cH[2] = bitRangeConvert(cH[2], 6, 8);
|
||||
|
||||
cV[0] = bitRangeConvert(cV[0], 6, 8);
|
||||
cV[1] = bitRangeConvert(cV[1], 7, 8);
|
||||
cV[2] = bitRangeConvert(cV[2], 6, 8);
|
||||
|
||||
int16_t dy[3];
|
||||
dy[0] = cV[0] - c0[0];
|
||||
dy[1] = cV[1] - c0[1];
|
||||
dy[2] = cV[2] - c0[2];
|
||||
|
||||
int16_t sx[3];
|
||||
sx[0] = int16_t(c0[0])<<2;
|
||||
sx[1] = int16_t(c0[1])<<2;
|
||||
sx[2] = int16_t(c0[2])<<2;
|
||||
|
||||
int16_t ex[3];
|
||||
ex[0] = int16_t(cH[0])<<2;
|
||||
ex[1] = int16_t(cH[1])<<2;
|
||||
ex[2] = int16_t(cH[2])<<2;
|
||||
|
||||
for (int32_t vv = 0; vv < 4; ++vv)
|
||||
{
|
||||
int16_t dx[3];
|
||||
dx[0] = (ex[0] - sx[0])>>2;
|
||||
dx[1] = (ex[1] - sx[1])>>2;
|
||||
dx[2] = (ex[2] - sx[2])>>2;
|
||||
|
||||
for (int32_t hh = 0; hh < 4; ++hh)
|
||||
{
|
||||
const uint32_t idx = (vv<<4) + (hh<<2);
|
||||
|
||||
_dst[idx + 0] = uint8_sat( (sx[2] + dx[2]*hh)>>2);
|
||||
_dst[idx + 1] = uint8_sat( (sx[1] + dx[1]*hh)>>2);
|
||||
_dst[idx + 2] = uint8_sat( (sx[0] + dx[0]*hh)>>2);
|
||||
_dst[idx + 3] = 255;
|
||||
}
|
||||
|
||||
sx[0] += dy[0];
|
||||
sx[1] += dy[1];
|
||||
sx[2] += dy[2];
|
||||
|
||||
ex[0] += dy[0];
|
||||
ex[1] += dy[1];
|
||||
ex[2] += dy[2];
|
||||
}
|
||||
}
|
||||
|
||||
void decodeBlockEtc12(uint8_t _dst[16*4], const uint8_t _src[8])
|
||||
{
|
||||
bool flipBit = 0 != (_src[3] & 0x1);
|
||||
bool diffBit = 0 != (_src[3] & 0x2);
|
||||
|
@ -477,20 +709,38 @@ namespace bgfx
|
|||
rgb[2] = _src[2] >> 3;
|
||||
|
||||
int8_t diff[3];
|
||||
diff[0] = int8_t( (_src[0] & 0x07)<<5)>>5;
|
||||
diff[1] = int8_t( (_src[1] & 0x07)<<5)>>5;
|
||||
diff[2] = int8_t( (_src[2] & 0x07)<<5)>>5;
|
||||
diff[0] = int8_t( (_src[0] & 0x7)<<5)>>5;
|
||||
diff[1] = int8_t( (_src[1] & 0x7)<<5)>>5;
|
||||
diff[2] = int8_t( (_src[2] & 0x7)<<5)>>5;
|
||||
|
||||
rgb[4] = rgb[0] + diff[0];
|
||||
rgb[5] = rgb[1] + diff[1];
|
||||
rgb[6] = rgb[2] + diff[2];
|
||||
int8_t rr = rgb[0] + diff[0];
|
||||
int8_t gg = rgb[1] + diff[1];
|
||||
int8_t bb = rgb[2] + diff[2];
|
||||
|
||||
// Etc2 3-modes
|
||||
if (rr < 0 || rr > 31)
|
||||
{
|
||||
decodeBlockEtc2ModeT(_dst, _src);
|
||||
return;
|
||||
}
|
||||
if (gg < 0 || gg > 31)
|
||||
{
|
||||
decodeBlockEtc2ModeH(_dst, _src);
|
||||
return;
|
||||
}
|
||||
if (bb < 0 || bb > 31)
|
||||
{
|
||||
decodeBlockEtc2ModePlanar(_dst, _src);
|
||||
return;
|
||||
}
|
||||
|
||||
// Etc1
|
||||
rgb[0] = bitRangeConvert(rgb[0], 5, 8);
|
||||
rgb[1] = bitRangeConvert(rgb[1], 5, 8);
|
||||
rgb[2] = bitRangeConvert(rgb[2], 5, 8);
|
||||
rgb[4] = bitRangeConvert(rgb[4], 5, 8);
|
||||
rgb[5] = bitRangeConvert(rgb[5], 5, 8);
|
||||
rgb[6] = bitRangeConvert(rgb[6], 5, 8);
|
||||
rgb[4] = bitRangeConvert(rr, 5, 8);
|
||||
rgb[5] = bitRangeConvert(gg, 5, 8);
|
||||
rgb[6] = bitRangeConvert(bb, 5, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -525,12 +775,13 @@ namespace bgfx
|
|||
const uint32_t color = block<<2;
|
||||
const uint32_t idx = (ii&0xc) | ( (ii & 0x3)<<4);
|
||||
const uint32_t lsbi = indexLsb & 1;
|
||||
const uint32_t msbi = indexMsb & 1;
|
||||
const int32_t mod = s_mod[table[block] ][lsbi + msbi*2];
|
||||
const uint32_t msbi = (indexMsb & 1)<<1;
|
||||
const int32_t mod = s_etc1Mod[table[block] ][lsbi | msbi];
|
||||
|
||||
_dst[idx + 0] = uint8_satadd(rgb[color+2], mod);
|
||||
_dst[idx + 1] = uint8_satadd(rgb[color+1], mod);
|
||||
_dst[idx + 2] = uint8_satadd(rgb[color+0], mod);
|
||||
_dst[idx + 3] = 255;
|
||||
|
||||
indexLsb >>= 1;
|
||||
indexMsb >>= 1;
|
||||
|
@ -544,12 +795,13 @@ namespace bgfx
|
|||
const uint32_t color = block<<2;
|
||||
const uint32_t idx = (ii&0xc) | ( (ii & 0x3)<<4);
|
||||
const uint32_t lsbi = indexLsb & 1;
|
||||
const uint32_t msbi = indexMsb & 1;
|
||||
const int32_t mod = s_mod[table[block] ][lsbi + msbi*2];
|
||||
const uint32_t msbi = (indexMsb & 1)<<1;
|
||||
const int32_t mod = s_etc1Mod[table[block] ][lsbi | msbi];
|
||||
|
||||
_dst[idx + 0] = uint8_satadd(rgb[color+2], mod);
|
||||
_dst[idx + 1] = uint8_satadd(rgb[color+1], mod);
|
||||
_dst[idx + 2] = uint8_satadd(rgb[color+0], mod);
|
||||
_dst[idx + 3] = 255;
|
||||
|
||||
indexLsb >>= 1;
|
||||
indexMsb >>= 1;
|
||||
|
@ -1197,11 +1449,12 @@ namespace bgfx
|
|||
break;
|
||||
|
||||
case TextureFormat::ETC1:
|
||||
case TextureFormat::ETC2:
|
||||
for (uint32_t yy = 0; yy < height; ++yy)
|
||||
{
|
||||
for (uint32_t xx = 0; xx < width; ++xx)
|
||||
{
|
||||
decodeBlockEtc1(temp, src);
|
||||
decodeBlockEtc12(temp, src);
|
||||
src += 8;
|
||||
|
||||
uint8_t* dst = &_dst[(yy*pitch+xx*4)*4];
|
||||
|
@ -1213,11 +1466,6 @@ namespace bgfx
|
|||
}
|
||||
break;
|
||||
|
||||
case TextureFormat::ETC2:
|
||||
BX_WARN(false, "ETC2 decoder is not implemented.");
|
||||
imageCheckerboard(_width, _height, 16, UINT32_C(0xff000000), UINT32_C(0xff0000ff), _dst);
|
||||
break;
|
||||
|
||||
case TextureFormat::ETC2A:
|
||||
BX_WARN(false, "ETC2A decoder is not implemented.");
|
||||
imageCheckerboard(_width, _height, 16, UINT32_C(0xff000000), UINT32_C(0xff00ff00), _dst);
|
||||
|
|
Loading…
Reference in a new issue