mirror of
https://github.com/scratchfoundation/bgfx.git
synced 2024-11-28 18:45:54 -05:00
Added PTC14(A) decoding fallback.
This commit is contained in:
parent
6998941b8f
commit
01ac66258e
1 changed files with 312 additions and 20 deletions
300
src/image.cpp
300
src/image.cpp
|
@ -941,6 +941,276 @@ namespace bgfx
|
|||
}
|
||||
}
|
||||
|
||||
static const uint8_t s_pvrtcFactors[16][4] =
|
||||
{
|
||||
{ 4, 4, 4, 4 },
|
||||
{ 2, 6, 2, 6 },
|
||||
{ 8, 0, 8, 0 },
|
||||
{ 6, 2, 6, 2 },
|
||||
|
||||
{ 2, 2, 6, 6 },
|
||||
{ 1, 3, 3, 9 },
|
||||
{ 4, 0, 12, 0 },
|
||||
{ 3, 1, 9, 3 },
|
||||
|
||||
{ 8, 8, 0, 0 },
|
||||
{ 4, 12, 0, 0 },
|
||||
{ 16, 0, 0, 0 },
|
||||
{ 12, 4, 0, 0 },
|
||||
|
||||
{ 6, 6, 2, 2 },
|
||||
{ 3, 9, 1, 3 },
|
||||
{ 12, 0, 4, 0 },
|
||||
{ 9, 3, 3, 1 },
|
||||
};
|
||||
|
||||
static const uint8_t s_pvrtcWeights[8][4] =
|
||||
{
|
||||
{ 8, 0, 8, 0 },
|
||||
{ 5, 3, 5, 3 },
|
||||
{ 3, 5, 3, 5 },
|
||||
{ 0, 8, 0, 8 },
|
||||
|
||||
{ 8, 0, 8, 0 },
|
||||
{ 4, 4, 4, 4 },
|
||||
{ 4, 4, 0, 0 },
|
||||
{ 0, 8, 0, 8 },
|
||||
};
|
||||
|
||||
uint32_t morton2d(uint16_t _x, uint16_t _y)
|
||||
{
|
||||
using namespace bx;
|
||||
const uint32_t tmpx = uint32_part1by1(_x);
|
||||
const uint32_t xbits = uint32_sll(tmpx, 1);
|
||||
const uint32_t ybits = uint32_part1by1(_y);
|
||||
const uint32_t result = uint32_or(xbits, ybits);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t getColor(const uint8_t _src[8])
|
||||
{
|
||||
return 0
|
||||
| _src[7]<<24
|
||||
| _src[6]<<16
|
||||
| _src[5]<<8
|
||||
| _src[4]
|
||||
;
|
||||
}
|
||||
|
||||
void decodeBlockPtc14RgbAddA(uint32_t _block, uint32_t* _r, uint32_t* _g, uint32_t* _b, uint8_t _factor)
|
||||
{
|
||||
if (0 != (_block & (1<<15) ) )
|
||||
{
|
||||
*_r += bitRangeConvert( (_block >> 10) & 0x1f, 5, 8) * _factor;
|
||||
*_g += bitRangeConvert( (_block >> 5) & 0x1f, 5, 8) * _factor;
|
||||
*_b += bitRangeConvert( (_block >> 1) & 0x0f, 4, 8) * _factor;
|
||||
}
|
||||
else
|
||||
{
|
||||
*_r += bitRangeConvert( (_block >> 8) & 0xf, 4, 8) * _factor;
|
||||
*_g += bitRangeConvert( (_block >> 4) & 0xf, 4, 8) * _factor;
|
||||
*_b += bitRangeConvert( (_block >> 1) & 0x7, 3, 8) * _factor;
|
||||
}
|
||||
}
|
||||
|
||||
void decodeBlockPtc14RgbAddB(uint32_t _block, uint32_t* _r, uint32_t* _g, uint32_t* _b, uint8_t _factor)
|
||||
{
|
||||
if (0 != (_block & (1<<31) ) )
|
||||
{
|
||||
*_r += bitRangeConvert( (_block >> 26) & 0x1f, 5, 8) * _factor;
|
||||
*_g += bitRangeConvert( (_block >> 21) & 0x1f, 5, 8) * _factor;
|
||||
*_b += bitRangeConvert( (_block >> 16) & 0x1f, 5, 8) * _factor;
|
||||
}
|
||||
else
|
||||
{
|
||||
*_r += bitRangeConvert( (_block >> 24) & 0xf, 4, 8) * _factor;
|
||||
*_g += bitRangeConvert( (_block >> 20) & 0xf, 4, 8) * _factor;
|
||||
*_b += bitRangeConvert( (_block >> 16) & 0xf, 4, 8) * _factor;
|
||||
}
|
||||
}
|
||||
|
||||
void decodeBlockPtc14(uint8_t _dst[16*4], const uint8_t* _src, uint32_t _x, uint32_t _y, uint32_t _width, uint32_t _height)
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7
|
||||
// 7654321076543210765432107654321076543210765432107654321076543210
|
||||
// mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmyrrrrrgggggbbbbbxrrrrrgggggbbbbp
|
||||
// ^ ^^ ^^ ^
|
||||
// +-- modulation data |+- B color |+- A color |
|
||||
// +-- B opaque +-- A opaque |
|
||||
// alpha punchthrough --+
|
||||
|
||||
const uint8_t* bc = &_src[morton2d(_x, _y) * 8];
|
||||
|
||||
uint32_t mod = 0
|
||||
| bc[3]<<24
|
||||
| bc[2]<<16
|
||||
| bc[1]<<8
|
||||
| bc[0]
|
||||
;
|
||||
|
||||
const bool punchthrough = !!(bc[7] & 1);
|
||||
const uint8_t* weightTable = s_pvrtcWeights[4 * punchthrough];
|
||||
const uint8_t* factorTable = s_pvrtcFactors[0];
|
||||
|
||||
for (int yy = 0; yy < 4; ++yy)
|
||||
{
|
||||
const uint32_t yOffset = (yy < 2) ? -1 : 0;
|
||||
const uint32_t y0 = (_y + yOffset) % _height;
|
||||
const uint32_t y1 = (y0 + 1) % _height;
|
||||
|
||||
for (int xx = 0; xx < 4; ++xx)
|
||||
{
|
||||
const uint32_t xOffset = (xx < 2) ? -1 : 0;
|
||||
const uint32_t x0 = (_x + xOffset) % _width;
|
||||
const uint32_t x1 = (x0 + 1) % _width;
|
||||
|
||||
const uint32_t bc0 = getColor(&_src[morton2d(x0, y0) * 8]);
|
||||
const uint32_t bc1 = getColor(&_src[morton2d(x1, y0) * 8]);
|
||||
const uint32_t bc2 = getColor(&_src[morton2d(x0, y1) * 8]);
|
||||
const uint32_t bc3 = getColor(&_src[morton2d(x1, y1) * 8]);
|
||||
|
||||
const uint8_t f0 = factorTable[0];
|
||||
const uint8_t f1 = factorTable[1];
|
||||
const uint8_t f2 = factorTable[2];
|
||||
const uint8_t f3 = factorTable[3];
|
||||
|
||||
uint32_t ar = 0, ag = 0, ab = 0;
|
||||
decodeBlockPtc14RgbAddA(bc0, &ar, &ag, &ab, f0);
|
||||
decodeBlockPtc14RgbAddA(bc1, &ar, &ag, &ab, f1);
|
||||
decodeBlockPtc14RgbAddA(bc2, &ar, &ag, &ab, f2);
|
||||
decodeBlockPtc14RgbAddA(bc3, &ar, &ag, &ab, f3);
|
||||
|
||||
uint32_t br = 0, bg = 0, bb = 0;
|
||||
decodeBlockPtc14RgbAddB(bc0, &br, &bg, &bb, f0);
|
||||
decodeBlockPtc14RgbAddB(bc1, &br, &bg, &bb, f1);
|
||||
decodeBlockPtc14RgbAddB(bc2, &br, &bg, &bb, f2);
|
||||
decodeBlockPtc14RgbAddB(bc3, &br, &bg, &bb, f3);
|
||||
|
||||
const uint8_t* weight = &weightTable[(mod & 3)*4];
|
||||
const uint8_t wa = weight[0];
|
||||
const uint8_t wb = weight[1];
|
||||
|
||||
_dst[(yy*4 + xx)*4+0] = (ab * wa + bb * wb) >> 7;
|
||||
_dst[(yy*4 + xx)*4+1] = (ag * wa + bg * wb) >> 7;
|
||||
_dst[(yy*4 + xx)*4+2] = (ar * wa + br * wb) >> 7;
|
||||
_dst[(yy*4 + xx)*4+3] = 255;
|
||||
|
||||
mod >>= 2;
|
||||
factorTable += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void decodeBlockPtc14ARgbaAddA(uint32_t _block, uint32_t* _r, uint32_t* _g, uint32_t* _b, uint32_t* _a, uint8_t _factor)
|
||||
{
|
||||
if (0 != (_block & (1<<15) ) )
|
||||
{
|
||||
*_r += bitRangeConvert( (_block >> 10) & 0x1f, 5, 8) * _factor;
|
||||
*_g += bitRangeConvert( (_block >> 5) & 0x1f, 5, 8) * _factor;
|
||||
*_b += bitRangeConvert( (_block >> 1) & 0x0f, 4, 8) * _factor;
|
||||
*_a += 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
*_r += bitRangeConvert( (_block >> 8) & 0xf, 4, 8) * _factor;
|
||||
*_g += bitRangeConvert( (_block >> 4) & 0xf, 4, 8) * _factor;
|
||||
*_b += bitRangeConvert( (_block >> 1) & 0x7, 3, 8) * _factor;
|
||||
*_a += bitRangeConvert( (_block >> 12) & 0x7, 3, 8) * _factor;
|
||||
}
|
||||
}
|
||||
|
||||
void decodeBlockPtc14ARgbaAddB(uint32_t _block, uint32_t* _r, uint32_t* _g, uint32_t* _b, uint32_t* _a, uint8_t _factor)
|
||||
{
|
||||
if (0 != (_block & (1<<31) ) )
|
||||
{
|
||||
*_r += bitRangeConvert( (_block >> 26) & 0x1f, 5, 8) * _factor;
|
||||
*_g += bitRangeConvert( (_block >> 21) & 0x1f, 5, 8) * _factor;
|
||||
*_b += bitRangeConvert( (_block >> 16) & 0x1f, 5, 8) * _factor;
|
||||
*_a += 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
*_r += bitRangeConvert( (_block >> 24) & 0xf, 4, 8) * _factor;
|
||||
*_g += bitRangeConvert( (_block >> 20) & 0xf, 4, 8) * _factor;
|
||||
*_b += bitRangeConvert( (_block >> 16) & 0xf, 4, 8) * _factor;
|
||||
*_a += bitRangeConvert( (_block >> 28) & 0x7, 3, 8) * _factor;
|
||||
}
|
||||
}
|
||||
|
||||
void decodeBlockPtc14A(uint8_t _dst[16*4], const uint8_t* _src, uint32_t _x, uint32_t _y, uint32_t _width, uint32_t _height)
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7
|
||||
// 7654321076543210765432107654321076543210765432107654321076543210
|
||||
// mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmyrrrrrgggggbbbbbxrrrrrgggggbbbbp
|
||||
// ^ ^^ ^^ ^
|
||||
// +-- modulation data |+- B color |+- A color |
|
||||
// +-- B opaque +-- A opaque |
|
||||
// alpha punchthrough --+
|
||||
|
||||
const uint8_t* bc = &_src[morton2d(_x, _y) * 8];
|
||||
|
||||
uint32_t mod = 0
|
||||
| bc[3]<<24
|
||||
| bc[2]<<16
|
||||
| bc[1]<<8
|
||||
| bc[0]
|
||||
;
|
||||
|
||||
const bool punchthrough = !!(bc[7] & 1);
|
||||
const uint8_t* weightTable = s_pvrtcWeights[4 * punchthrough];
|
||||
const uint8_t* factorTable = s_pvrtcFactors[0];
|
||||
|
||||
for (int yy = 0; yy < 4; ++yy)
|
||||
{
|
||||
const uint32_t yOffset = (yy < 2) ? -1 : 0;
|
||||
const uint32_t y0 = (_y + yOffset) % _height;
|
||||
const uint32_t y1 = (y0 + 1) % _height;
|
||||
|
||||
for (int xx = 0; xx < 4; ++xx)
|
||||
{
|
||||
const uint32_t xOffset = (xx < 2) ? -1 : 0;
|
||||
const uint32_t x0 = (_x + xOffset) % _width;
|
||||
const uint32_t x1 = (x0 + 1) % _width;
|
||||
|
||||
const uint32_t bc0 = getColor(&_src[morton2d(x0, y0) * 8]);
|
||||
const uint32_t bc1 = getColor(&_src[morton2d(x1, y0) * 8]);
|
||||
const uint32_t bc2 = getColor(&_src[morton2d(x0, y1) * 8]);
|
||||
const uint32_t bc3 = getColor(&_src[morton2d(x1, y1) * 8]);
|
||||
|
||||
const uint8_t f0 = factorTable[0];
|
||||
const uint8_t f1 = factorTable[1];
|
||||
const uint8_t f2 = factorTable[2];
|
||||
const uint8_t f3 = factorTable[3];
|
||||
|
||||
uint32_t ar = 0, ag = 0, ab = 0, aa = 0;
|
||||
decodeBlockPtc14ARgbaAddA(bc0, &ar, &ag, &ab, &aa, f0);
|
||||
decodeBlockPtc14ARgbaAddA(bc1, &ar, &ag, &ab, &aa, f1);
|
||||
decodeBlockPtc14ARgbaAddA(bc2, &ar, &ag, &ab, &aa, f2);
|
||||
decodeBlockPtc14ARgbaAddA(bc3, &ar, &ag, &ab, &aa, f3);
|
||||
|
||||
uint32_t br = 0, bg = 0, bb = 0, ba = 0;
|
||||
decodeBlockPtc14ARgbaAddB(bc0, &br, &bg, &bb, &ba, f0);
|
||||
decodeBlockPtc14ARgbaAddB(bc1, &br, &bg, &bb, &ba, f1);
|
||||
decodeBlockPtc14ARgbaAddB(bc2, &br, &bg, &bb, &ba, f2);
|
||||
decodeBlockPtc14ARgbaAddB(bc3, &br, &bg, &bb, &ba, f3);
|
||||
|
||||
const uint8_t* weight = &weightTable[(mod & 3)*4];
|
||||
const uint8_t wa = weight[0];
|
||||
const uint8_t wb = weight[1];
|
||||
const uint8_t wc = weight[2];
|
||||
const uint8_t wd = weight[3];
|
||||
|
||||
_dst[(yy*4 + xx)*4+0] = (ab * wa + bb * wb) >> 7;
|
||||
_dst[(yy*4 + xx)*4+1] = (ag * wa + bg * wb) >> 7;
|
||||
_dst[(yy*4 + xx)*4+2] = (ar * wa + br * wb) >> 7;
|
||||
_dst[(yy*4 + xx)*4+3] = (aa * wc + ba * wd) >> 7;
|
||||
|
||||
mod >>= 2;
|
||||
factorTable += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DDS
|
||||
#define DDS_MAGIC BX_MAKEFOURCC('D', 'D', 'S', ' ')
|
||||
#define DDS_HEADER_SIZE 124
|
||||
|
@ -1774,13 +2044,35 @@ namespace bgfx
|
|||
break;
|
||||
|
||||
case TextureFormat::PTC14:
|
||||
BX_WARN(false, "PTC14 decoder is not implemented.");
|
||||
imageCheckerboard(_width, _height, 16, UINT32_C(0xff000000), UINT32_C(0xff00ffff), _dst);
|
||||
for (uint32_t yy = 0; yy < height; ++yy)
|
||||
{
|
||||
for (uint32_t xx = 0; xx < width; ++xx)
|
||||
{
|
||||
decodeBlockPtc14(temp, src, xx, yy, width, height);
|
||||
|
||||
uint8_t* dst = &_dst[(yy*_pitch+xx*4)*4];
|
||||
memcpy(&dst[0*_pitch], &temp[ 0], 16);
|
||||
memcpy(&dst[1*_pitch], &temp[16], 16);
|
||||
memcpy(&dst[2*_pitch], &temp[32], 16);
|
||||
memcpy(&dst[3*_pitch], &temp[48], 16);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TextureFormat::PTC14A:
|
||||
BX_WARN(false, "PTC14A decoder is not implemented.");
|
||||
imageCheckerboard(_width, _height, 16, UINT32_C(0xffff0000), UINT32_C(0xff0000ff), _dst);
|
||||
for (uint32_t yy = 0; yy < height; ++yy)
|
||||
{
|
||||
for (uint32_t xx = 0; xx < width; ++xx)
|
||||
{
|
||||
decodeBlockPtc14A(temp, src, xx, yy, width, height);
|
||||
|
||||
uint8_t* dst = &_dst[(yy*_pitch+xx*4)*4];
|
||||
memcpy(&dst[0*_pitch], &temp[ 0], 16);
|
||||
memcpy(&dst[1*_pitch], &temp[16], 16);
|
||||
memcpy(&dst[2*_pitch], &temp[32], 16);
|
||||
memcpy(&dst[3*_pitch], &temp[48], 16);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TextureFormat::PTC22:
|
||||
|
|
Loading…
Reference in a new issue