DXT textures now mostly working-ish (work left to do on alpha for DXT3/5)

This commit is contained in:
Henrik Rydgard 2012-11-28 16:12:29 +01:00
parent 6ff2964170
commit 5fb8e6dfb0
4 changed files with 161 additions and 27 deletions

View file

@ -303,7 +303,7 @@ void WriteUnchecked_U8(const u8 _iValue, const u32 _Address)
WriteToHardware<u8>(_Address, _iValue);
}
void WriteUnchecked_U8(const u16 _iValue, const u32 _Address)
void WriteUnchecked_U16(const u16 _iValue, const u32 _Address)
{
WriteToHardware<u16>(_Address, _iValue);
}

View file

@ -52,7 +52,7 @@ GLES_GPU::GLES_GPU(int renderWidth, int renderHeight)
renderWidthFactor_ = (float)renderWidth / 480.0f;
renderHeightFactor_ = (float)renderHeight / 272.0f;
shaderManager_ = &shaderManager;
TextureCache_Init();
// Sanity check gstate
if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) {
ERROR_LOG(G3D, "gstate has drifted out of sync!");
@ -61,6 +61,7 @@ GLES_GPU::GLES_GPU(int renderWidth, int renderHeight)
GLES_GPU::~GLES_GPU()
{
TextureCache_Shutdown();
for (auto iter = vfbs_.begin(); iter != vfbs_.end(); ++iter)
{
fbo_destroy((*iter)->fbo);
@ -479,7 +480,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff)
ERROR_LOG(G3D, "Signal with Jump UNIMPLEMENTED! signal/end: %04x %04x", signal, enddata);
break;
case 0x11:
ERROR_LOG(G3D, "Signal with Jump UNIMPLEMENTED! signal/end: %04x %04x", signal, enddata);
ERROR_LOG(G3D, "Signal with Call UNIMPLEMENTED! signal/end: %04x %04x", signal, enddata);
break;
case 0x12:
ERROR_LOG(G3D, "Signal with Return UNIMPLEMENTED! signal/end: %04x %04x", signal, enddata);

View file

@ -44,15 +44,30 @@ struct TexCacheEntry
typedef std::map<u64, TexCacheEntry> TexCache;
static TexCache cache;
u32 tmpTexBuf32[1024 * 1024];
u16 tmpTexBuf16[1024 * 1024];
u16 tmpTexBufRearrange[1024 * 1024];
u32 *tmpTexBuf32;
u16 *tmpTexBuf16;
u32 *tmpTexBufRearrange;
u32 clutBuf32[4096];
u16 clutBuf16[4096];
void TextureCache_Init()
{
tmpTexBuf32 = new u32[1024 * 512];
tmpTexBuf16 = new u16[1024 * 512];
tmpTexBufRearrange = new u32[1024 * 512];
}
void TextureCache_Shutdown()
{
delete [] tmpTexBuf32;
tmpTexBuf32 = 0;
delete [] tmpTexBuf16;
tmpTexBuf16 = 0;
delete [] tmpTexBufRearrange;
tmpTexBufRearrange = 0;
}
void TextureCache_Clear(bool delete_them)
{
if (delete_them)
@ -408,9 +423,23 @@ u16 convert5551(u16 c) {
struct DXT1Block
{
u8 lines[4];
u16 color1;
u16 color2;
u8 lines[4];
};
struct DXT3Block
{
DXT1Block color;
u16 alphaLines[4];
};
struct DXT5Block
{
DXT1Block color;
u32 alphadata2;
u16 alphadata1;
u8 alpha1; u8 alpha2;
};
inline u32 makecol(int r, int g, int b, int a)
@ -418,22 +447,24 @@ inline u32 makecol(int r, int g, int b, int a)
return (a << 24)|(r << 16)|(g << 8)|b;
}
void decodeDXT1Block(u32 *dst, const DXT1Block *src, int pitch)
inline u16 swap16(u16 data) {return (data >> 8) | (data << 8);}
void decodeDXT1Block(u32 *dst, const DXT1Block *src, int pitch, bool ignore1bitAlpha = false)
{
// S3TC Decoder
// Needs more speed and debugging.
u16 c1 = src->color1;
u16 c2 = src->color2;
int blue1 = Convert5To8(c1 & 0x1F);
int blue2 = Convert5To8(c2 & 0x1F);
u16 c1 = (src->color1);
u16 c2 = (src->color2);
int red1 = Convert5To8(c1 & 0x1F);
int red2 = Convert5To8(c2 & 0x1F);
int green1 = Convert6To8((c1 >> 5) & 0x3F);
int green2 = Convert6To8((c2 >> 5) & 0x3F);
int red1 = Convert5To8((c1 >> 11) & 0x1F);
int red2 = Convert5To8((c2 >> 11) & 0x1F);
int colors[4];
int blue1 = Convert5To8((c1 >> 11) & 0x1F);
int blue2 = Convert5To8((c2 >> 11) & 0x1F);
u32 colors[4];
colors[0] = makecol(red1, green1, blue1, 255);
colors[1] = makecol(red2, green2, blue2, 255);
if (c1 > c2)
if (c1 > c2 || ignore1bitAlpha)
{
int blue3 = ((blue2 - blue1) >> 1) - ((blue2 - blue1) >> 3);
int green3 = ((green2 - green1) >> 1) - ((green2 - green1) >> 3);
@ -454,8 +485,61 @@ void decodeDXT1Block(u32 *dst, const DXT1Block *src, int pitch)
int val = src->lines[y];
for (int x = 0; x < 4; x++)
{
dst[x] = colors[(val >> 6) & 3];
val <<= 2;
dst[x] = colors[val & 3];
val >>= 2;
}
dst += pitch;
}
}
void decodeDXT3Block(u32 *dst, const DXT3Block *src, int pitch)
{
decodeDXT1Block(dst, &src->color, pitch, true);
// Alpha: TODO
}
inline u8 lerp8(const DXT5Block *src, int n) {
float d = n / 7.0f;
return (u8)(src->alpha1 + (src->alpha2 - src->alpha1) * d);
}
inline u8 lerp6(const DXT5Block *src, int n) {
float d = n / 5.0f;
return (u8)(src->alpha1 + (src->alpha2 - src->alpha1) * d);
}
// The alpha channel is not 100% correct
void decodeDXT5Block(u32 *dst, const DXT5Block *src, int pitch)
{
decodeDXT1Block(dst, &src->color, pitch, true);
u8 alpha[8];
alpha[0] = src->alpha1;
alpha[1] = src->alpha2;
if (alpha[0] > alpha[1]) {
alpha[2] = lerp8(src, 6);
alpha[3] = lerp8(src, 5);
alpha[4] = lerp8(src, 4);
alpha[5] = lerp8(src, 3);
alpha[6] = lerp8(src, 2);
alpha[7] = lerp8(src, 1);
} else {
alpha[2] = lerp6(src, 4);
alpha[3] = lerp6(src, 3);
alpha[4] = lerp6(src, 2);
alpha[5] = lerp6(src, 1);
alpha[6] = 0;
alpha[7] = 255;
}
u64 data = ((u64)src->alphadata1 << 32) | src->alphadata2;
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
dst[x] = (dst[x] & 0xFFFFFF) | (alpha[data & 7] << 24);
data >>= 3;
}
dst += pitch;
}
@ -742,36 +826,83 @@ void PSPSetTexture()
break;
case GE_TFMT_DXT1:
ERROR_LOG(G3D, "Partial DXT1 texture decoding");
ERROR_LOG(G3D, "Partial DXT1 texture decoding. swizzle=%i w=%i h=%i bufw=%i", gstate.texmode & 1, w, h, bufw);
dstFmt = GL_UNSIGNED_BYTE;
{
memset(tmpTexBuf32, 0, 512*512*0);
// THIS IS VERY BROKEN but can be debugged! :)
u32 *dst = tmpTexBuf32;
DXT1Block *src = (DXT1Block*)texptr;
for (u32 y=0; y<h/4; y++)
for (int y = 0; y < h; y += 4)
{
u32 i = y*w/4;
for (u32 x=0; x<w/4; x++)
u32 blockIndex = (y / 4) * (bufw / 4);
for (int x = 0; x < w; x += 4)
{
decodeDXT1Block(dst + w*4 * y * 4 + x * 4, src + i, w);
i++;
decodeDXT1Block(dst + bufw * y + x, src + blockIndex, bufw);
blockIndex++;
}
}
finalBuf = tmpTexBuf32;
w = (w + 3) & ~3;
}
break;
case GE_TFMT_DXT3:
dstFmt = GL_UNSIGNED_BYTE;
{
memset(tmpTexBuf32, 0, 512*512*0);
// THIS IS VERY BROKEN but can be debugged! :)
u32 *dst = tmpTexBuf32;
DXT3Block *src = (DXT3Block*)texptr;
for (int y = 0; y < h; y += 4)
{
u32 blockIndex = (y / 4) * (bufw / 8);
for (int x = 0; x < bufw; x += 4)
{
decodeDXT3Block(dst + bufw * y + x, src + blockIndex, bufw);
blockIndex++;
}
}
w = (w + 3) & ~3;
finalBuf = tmpTexBuf32;
}
break;
case GE_TFMT_DXT5:
ERROR_LOG(G3D, "Unhandled compressed texture!");
ERROR_LOG(G3D, "Unhandled compressed texture, format %i! swizzle=%i", format, gstate.texmode & 1);
dstFmt = GL_UNSIGNED_BYTE;
{
memset(tmpTexBuf32, 0, 512*512*0);
// THIS IS VERY BROKEN but can be debugged! :)
u32 *dst = tmpTexBuf32;
DXT5Block *src = (DXT5Block*)texptr;
for (int y = 0; y < h; y += 4)
{
u32 blockIndex = (y / 4) * (bufw / 4);
for (int x = 0; x < bufw; x += 4)
{
decodeDXT5Block(dst + bufw * y + x, src + blockIndex, bufw);
blockIndex++;
}
}
w = (w + 3) & ~3;
finalBuf = tmpTexBuf32;
}
break;
default:
ERROR_LOG(G3D, "Unknown Texture Format %d!!!", format);
finalBuf = tmpTexBuf32;
return;
}
if (!finalBuf) {
ERROR_LOG(G3D, "NO finalbuf! Will crash!");
}
convertColors((u8*)finalBuf, dstFmt, bufw * h);
if (w != bufw) {

View file

@ -21,6 +21,8 @@
void PSPSetTexture();
void TextureCache_Init();
void TextureCache_Shutdown();
void TextureCache_Clear(bool delete_them);
void TextureCache_Decimate(); // Run this once per frame to get rid of old textures.
int TextureCache_NumLoadedTextures();