mirror of
https://github.com/scratchfoundation/bgfx.git
synced 2024-11-28 18:45:54 -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},
|
{ 2, 8, -2, -8},
|
||||||
{ 15, 17, -15, -17},
|
{ 15, 17, -15, -17},
|
||||||
|
@ -454,16 +454,248 @@ namespace bgfx
|
||||||
{ 47, 183, -47, -183},
|
{ 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;
|
using namespace bx;
|
||||||
const int32_t add = _a + _b;
|
const uint32_t min = uint32_imin(_a, 255);
|
||||||
const uint32_t min = uint32_imin(add, 255);
|
|
||||||
const uint32_t result = uint32_imax(min, 0);
|
const uint32_t result = uint32_imax(min, 0);
|
||||||
return (uint8_t)result;
|
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 flipBit = 0 != (_src[3] & 0x1);
|
||||||
bool diffBit = 0 != (_src[3] & 0x2);
|
bool diffBit = 0 != (_src[3] & 0x2);
|
||||||
|
@ -477,20 +709,38 @@ namespace bgfx
|
||||||
rgb[2] = _src[2] >> 3;
|
rgb[2] = _src[2] >> 3;
|
||||||
|
|
||||||
int8_t diff[3];
|
int8_t diff[3];
|
||||||
diff[0] = int8_t( (_src[0] & 0x07)<<5)>>5;
|
diff[0] = int8_t( (_src[0] & 0x7)<<5)>>5;
|
||||||
diff[1] = int8_t( (_src[1] & 0x07)<<5)>>5;
|
diff[1] = int8_t( (_src[1] & 0x7)<<5)>>5;
|
||||||
diff[2] = int8_t( (_src[2] & 0x07)<<5)>>5;
|
diff[2] = int8_t( (_src[2] & 0x7)<<5)>>5;
|
||||||
|
|
||||||
rgb[4] = rgb[0] + diff[0];
|
int8_t rr = rgb[0] + diff[0];
|
||||||
rgb[5] = rgb[1] + diff[1];
|
int8_t gg = rgb[1] + diff[1];
|
||||||
rgb[6] = rgb[2] + diff[2];
|
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[0] = bitRangeConvert(rgb[0], 5, 8);
|
||||||
rgb[1] = bitRangeConvert(rgb[1], 5, 8);
|
rgb[1] = bitRangeConvert(rgb[1], 5, 8);
|
||||||
rgb[2] = bitRangeConvert(rgb[2], 5, 8);
|
rgb[2] = bitRangeConvert(rgb[2], 5, 8);
|
||||||
rgb[4] = bitRangeConvert(rgb[4], 5, 8);
|
rgb[4] = bitRangeConvert(rr, 5, 8);
|
||||||
rgb[5] = bitRangeConvert(rgb[5], 5, 8);
|
rgb[5] = bitRangeConvert(gg, 5, 8);
|
||||||
rgb[6] = bitRangeConvert(rgb[6], 5, 8);
|
rgb[6] = bitRangeConvert(bb, 5, 8);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -525,12 +775,13 @@ namespace bgfx
|
||||||
const uint32_t color = block<<2;
|
const uint32_t color = block<<2;
|
||||||
const uint32_t idx = (ii&0xc) | ( (ii & 0x3)<<4);
|
const uint32_t idx = (ii&0xc) | ( (ii & 0x3)<<4);
|
||||||
const uint32_t lsbi = indexLsb & 1;
|
const uint32_t lsbi = indexLsb & 1;
|
||||||
const uint32_t msbi = indexMsb & 1;
|
const uint32_t msbi = (indexMsb & 1)<<1;
|
||||||
const int32_t mod = s_mod[table[block] ][lsbi + msbi*2];
|
const int32_t mod = s_etc1Mod[table[block] ][lsbi | msbi];
|
||||||
|
|
||||||
_dst[idx + 0] = uint8_satadd(rgb[color+2], mod);
|
_dst[idx + 0] = uint8_satadd(rgb[color+2], mod);
|
||||||
_dst[idx + 1] = uint8_satadd(rgb[color+1], mod);
|
_dst[idx + 1] = uint8_satadd(rgb[color+1], mod);
|
||||||
_dst[idx + 2] = uint8_satadd(rgb[color+0], mod);
|
_dst[idx + 2] = uint8_satadd(rgb[color+0], mod);
|
||||||
|
_dst[idx + 3] = 255;
|
||||||
|
|
||||||
indexLsb >>= 1;
|
indexLsb >>= 1;
|
||||||
indexMsb >>= 1;
|
indexMsb >>= 1;
|
||||||
|
@ -544,12 +795,13 @@ namespace bgfx
|
||||||
const uint32_t color = block<<2;
|
const uint32_t color = block<<2;
|
||||||
const uint32_t idx = (ii&0xc) | ( (ii & 0x3)<<4);
|
const uint32_t idx = (ii&0xc) | ( (ii & 0x3)<<4);
|
||||||
const uint32_t lsbi = indexLsb & 1;
|
const uint32_t lsbi = indexLsb & 1;
|
||||||
const uint32_t msbi = indexMsb & 1;
|
const uint32_t msbi = (indexMsb & 1)<<1;
|
||||||
const int32_t mod = s_mod[table[block] ][lsbi + msbi*2];
|
const int32_t mod = s_etc1Mod[table[block] ][lsbi | msbi];
|
||||||
|
|
||||||
_dst[idx + 0] = uint8_satadd(rgb[color+2], mod);
|
_dst[idx + 0] = uint8_satadd(rgb[color+2], mod);
|
||||||
_dst[idx + 1] = uint8_satadd(rgb[color+1], mod);
|
_dst[idx + 1] = uint8_satadd(rgb[color+1], mod);
|
||||||
_dst[idx + 2] = uint8_satadd(rgb[color+0], mod);
|
_dst[idx + 2] = uint8_satadd(rgb[color+0], mod);
|
||||||
|
_dst[idx + 3] = 255;
|
||||||
|
|
||||||
indexLsb >>= 1;
|
indexLsb >>= 1;
|
||||||
indexMsb >>= 1;
|
indexMsb >>= 1;
|
||||||
|
@ -1197,11 +1449,12 @@ namespace bgfx
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TextureFormat::ETC1:
|
case TextureFormat::ETC1:
|
||||||
|
case TextureFormat::ETC2:
|
||||||
for (uint32_t yy = 0; yy < height; ++yy)
|
for (uint32_t yy = 0; yy < height; ++yy)
|
||||||
{
|
{
|
||||||
for (uint32_t xx = 0; xx < width; ++xx)
|
for (uint32_t xx = 0; xx < width; ++xx)
|
||||||
{
|
{
|
||||||
decodeBlockEtc1(temp, src);
|
decodeBlockEtc12(temp, src);
|
||||||
src += 8;
|
src += 8;
|
||||||
|
|
||||||
uint8_t* dst = &_dst[(yy*pitch+xx*4)*4];
|
uint8_t* dst = &_dst[(yy*pitch+xx*4)*4];
|
||||||
|
@ -1213,11 +1466,6 @@ namespace bgfx
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case TextureFormat::ETC2A:
|
||||||
BX_WARN(false, "ETC2A decoder is not implemented.");
|
BX_WARN(false, "ETC2A decoder is not implemented.");
|
||||||
imageCheckerboard(_width, _height, 16, UINT32_C(0xff000000), UINT32_C(0xff00ff00), _dst);
|
imageCheckerboard(_width, _height, 16, UINT32_C(0xff000000), UINT32_C(0xff00ff00), _dst);
|
||||||
|
|
Loading…
Reference in a new issue