summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/Src/TextureDecoder.cpp
diff options
context:
space:
mode:
authordonkopunchstania <donkopunchstania@gmail.com>2009-10-10 21:19:39 +0000
committerdonkopunchstania <donkopunchstania@gmail.com>2009-10-10 21:19:39 +0000
commit56214e91037279fb16cca0af75c1dec2d8432426 (patch)
tree353ae7939c065e55d08e425553482d64668f112f /Source/Core/VideoCommon/Src/TextureDecoder.cpp
parent5049fcf9f547676aba022d3be8e1b2145b24e9b4 (diff)
Moving pixel engine and command processor from core to video common. This will break previous save states. Adds decoding single pixels to texture decoder.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4391 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core/VideoCommon/Src/TextureDecoder.cpp')
-rw-r--r--Source/Core/VideoCommon/Src/TextureDecoder.cpp337
1 files changed, 337 insertions, 0 deletions
diff --git a/Source/Core/VideoCommon/Src/TextureDecoder.cpp b/Source/Core/VideoCommon/Src/TextureDecoder.cpp
index 302f1c6704..9c09ad37cb 100644
--- a/Source/Core/VideoCommon/Src/TextureDecoder.cpp
+++ b/Source/Core/VideoCommon/Src/TextureDecoder.cpp
@@ -325,6 +325,11 @@ inline u32 makecol(int r, int g, int b, int a)
return (a << 24)|(r << 16)|(g << 8)|b;
}
+inline u32 makeRGBA(int r, int g, int b, int a)
+{
+ return (a<<24)|(b<<16)|(g<<8)|r;
+}
+
void decodeDXTBlock(u32 *dst, const DXTBlock *src, int pitch)
{
// S3TC Decoder (Note: GCN decodes differently from PC so we can't use native support)
@@ -664,6 +669,338 @@ PC_TexFormat TexDecoder_Decode(u8 *dst, const u8 *src, int width, int height, in
return retval;
}
+
+inline u32 decode565RGBA(u16 val)
+{
+ int r,g,b,a;
+ r=Convert5To8((val>>11) & 0x1f);
+ g=Convert6To8((val>>5 ) & 0x3f);
+ b=Convert5To8((val ) & 0x1f);
+ a=0xFF;
+ return r | (g<<8) | (b << 16) | (a << 24);
+}
+
+inline u32 decodeIA8Swapped(u16 val)
+{
+ int a = val & 0xFF;
+ int i = val >> 8;
+ return i | (i<<8) | (i<<16) | (a<<24);
+}
+
+inline u32 decode5A3RGBA(u16 val)
+{
+ int r,g,b,a;
+ if ((val&0x8000))
+ {
+ r=Convert5To8((val>>10) & 0x1f);
+ g=Convert5To8((val>>5 ) & 0x1f);
+ b=Convert5To8((val ) & 0x1f);
+ a=0xFF;
+ }
+ else
+ {
+ a=Convert3To8((val>>12) & 0x7);
+ r=Convert4To8((val>>8 ) & 0xf);
+ g=Convert4To8((val>>4 ) & 0xf);
+ b=Convert4To8((val ) & 0xf);
+ }
+ return r | (g<<8) | (b << 16) | (a << 24);
+}
+
+
+void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth, int texformat, int tlutaddr, int tlutfmt)
+{
+ /* General formula for computing texture offset
+ //
+ u16 sBlk = s / blockWidth;
+ u16 tBlk = t / blockHeight;
+ u16 widthBlks = (width / blockWidth) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) * blockWidth * blockHeight;
+ u16 blkS = s & (blockWidth - 1);
+ u16 blkT = t & (blockHeight - 1);
+ u32 blkOff = blkT * blockWidth + blkS;
+ */
+
+ switch (texformat)
+ {
+ case GX_TF_C4:
+ {
+ u16 sBlk = s >> 3;
+ u16 tBlk = t >> 3;
+ u16 widthBlks = (imageWidth >> 3) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 5;
+ u16 blkS = s & 7;
+ u16 blkT = t & 7;
+ u32 blkOff = (blkT << 3) + blkS;
+
+ int rs = (blkOff & 1)?0:4;
+ u32 offset = base + (blkOff >> 1);
+
+ u8 val = (*(src + offset) >> rs) & 0xF;
+ u16 *tlut = (u16*)(texMem + tlutaddr);
+
+ switch (tlutfmt)
+ {
+ case 0:
+ *((u32*)dst) = decodeIA8Swapped(tlut[val]);
+ break;
+ case 1:
+ *((u32*)dst) = decode565RGBA(Common::swap16(tlut[val]));
+ break;
+ case 2:
+ *((u32*)dst) = decode5A3RGBA(Common::swap16(tlut[val]));
+ break;
+ }
+ }
+ break;
+ case GX_TF_I4:
+ {
+ u16 sBlk = s >> 3;
+ u16 tBlk = t >> 3;
+ u16 widthBlks = (imageWidth >> 3) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 5;
+ u16 blkS = s & 7;
+ u16 blkT = t & 7;
+ u32 blkOff = (blkT << 3) + blkS;
+
+ int rs = (blkOff & 1)?0:4;
+ u32 offset = base + (blkOff >> 1);
+
+ u8 val = (*(src + offset) >> rs) & 0xF;
+ val = Convert4To8(val);
+ dst[0] = val;
+ dst[1] = val;
+ dst[2] = val;
+ dst[3] = val;
+ }
+ break;
+ case GX_TF_I8:
+ {
+ u16 sBlk = s >> 3;
+ u16 tBlk = t >> 2;
+ u16 widthBlks = (imageWidth >> 3) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 5;
+ u16 blkS = s & 7;
+ u16 blkT = t & 3;
+ u32 blkOff = (blkT << 3) + blkS;
+
+ u8 val = *(src + base + blkOff);
+ dst[0] = val;
+ dst[1] = val;
+ dst[2] = val;
+ dst[3] = val;
+ }
+ break;
+ case GX_TF_C8:
+ {
+ u16 sBlk = s >> 3;
+ u16 tBlk = t >> 2;
+ u16 widthBlks = (imageWidth >> 3) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 5;
+ u16 blkS = s & 7;
+ u16 blkT = t & 3;
+ u32 blkOff = (blkT << 3) + blkS;
+
+ u8 val = *(src + base + blkOff);
+ u16 *tlut = (u16*)(texMem + tlutaddr);
+
+ switch (tlutfmt)
+ {
+ case 0:
+ *((u32*)dst) = decodeIA8Swapped(tlut[val]);
+ break;
+ case 1:
+ *((u32*)dst) = decode565RGBA(Common::swap16(tlut[val]));
+ break;
+ case 2:
+ *((u32*)dst) = decode5A3RGBA(Common::swap16(tlut[val]));
+ break;
+ }
+ }
+ break;
+ case GX_TF_IA4:
+ {
+ u16 sBlk = s >> 3;
+ u16 tBlk = t >> 2;
+ u16 widthBlks = (imageWidth >> 3) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 5;
+ u16 blkS = s & 7;
+ u16 blkT = t & 3;
+ u32 blkOff = (blkT << 3) + blkS;
+
+ u8 val = *(src + base + blkOff);
+ const u8 a = Convert4To8(val>>4);
+ const u8 l = Convert4To8(val&0xF);
+ dst[0] = l;
+ dst[1] = l;
+ dst[2] = l;
+ dst[3] = a;
+ }
+ break;
+ case GX_TF_IA8:
+ {
+ u16 sBlk = s >> 2;
+ u16 tBlk = t >> 2;
+ u16 widthBlks = (imageWidth >> 2) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 4;
+ u16 blkS = s & 3;
+ u16 blkT = t & 3;
+ u32 blkOff = (blkT << 2) + blkS;
+
+ u32 offset = (base + blkOff) << 1;
+ const u16* valAddr = (u16*)(src + offset);
+
+ *((u32*)dst) = decodeIA8Swapped(*valAddr);
+ }
+ break;
+ case GX_TF_C14X2:
+ {
+ u16 sBlk = s >> 2;
+ u16 tBlk = t >> 2;
+ u16 widthBlks = (imageWidth >> 2) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 4;
+ u16 blkS = s & 3;
+ u16 blkT = t & 3;
+ u32 blkOff = (blkT << 2) + blkS;
+
+ u32 offset = (base + blkOff) << 1;
+ const u16* valAddr = (u16*)(src + offset);
+
+ u16 val = Common::swap16(*valAddr) & 0x3FFF;
+ u16 *tlut = (u16*)(texMem + tlutaddr);
+
+ switch (tlutfmt)
+ {
+ case 0:
+ *((u32*)dst) = decodeIA8Swapped(tlut[val]);
+ break;
+ case 1:
+ *((u32*)dst) = decode565RGBA(Common::swap16(tlut[val]));
+ break;
+ case 2:
+ *((u32*)dst) = decode5A3RGBA(Common::swap16(tlut[val]));
+ break;
+ }
+ }
+ break;
+ case GX_TF_RGB565:
+ {
+ u16 sBlk = s >> 2;
+ u16 tBlk = t >> 2;
+ u16 widthBlks = (imageWidth >> 2) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 4;
+ u16 blkS = s & 3;
+ u16 blkT = t & 3;
+ u32 blkOff = (blkT << 2) + blkS;
+
+ u32 offset = (base + blkOff) << 1;
+ const u16* valAddr = (u16*)(src + offset);
+
+ *((u32*)dst) = decode565RGBA(Common::swap16(*valAddr));
+ }
+ break;
+ case GX_TF_RGB5A3:
+ {
+ u16 sBlk = s >> 2;
+ u16 tBlk = t >> 2;
+ u16 widthBlks = (imageWidth >> 2) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 4;
+ u16 blkS = s & 3;
+ u16 blkT = t & 3;
+ u32 blkOff = (blkT << 2) + blkS;
+
+ u32 offset = (base + blkOff) << 1;
+ const u16* valAddr = (u16*)(src + offset);
+
+ *((u32*)dst) = decode5A3RGBA(Common::swap16(*valAddr));
+ }
+ break;
+ case GX_TF_RGBA8:
+ {
+ u16 sBlk = s >> 2;
+ u16 tBlk = t >> 2;
+ u16 widthBlks = (imageWidth >> 2) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 5; // shift by 5 is correct
+ u16 blkS = s & 3;
+ u16 blkT = t & 3;
+ u32 blkOff = (blkT << 2) + blkS;
+
+ u32 offset = (base + blkOff) << 1 ;
+ const u8* valAddr = src + offset;
+
+ dst[3] = valAddr[0];
+ dst[0] = valAddr[1];
+ dst[1] = valAddr[32];
+ dst[2] = valAddr[33];
+ }
+ break;
+ case GX_TF_CMPR:
+ {
+ u16 sDxt = s >> 2;
+ u16 tDxt = t >> 2;
+
+ u16 sBlk = sDxt >> 1;
+ u16 tBlk = tDxt >> 1;
+ u16 widthBlks = (imageWidth >> 3) + 1;
+ u32 base = (tBlk * widthBlks + sBlk) << 2;
+ u16 blkS = sDxt & 1;
+ u16 blkT = tDxt & 1;
+ u32 blkOff = (blkT << 1) + blkS;
+
+ u32 offset = (base + blkOff) << 3;
+
+ const DXTBlock* dxtBlock = (const DXTBlock*)(src + offset);
+
+ u16 c1 = Common::swap16(dxtBlock->color1);
+ u16 c2 = Common::swap16(dxtBlock->color2);
+ int blue1 = Convert5To8(c1 & 0x1F);
+ int blue2 = 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);
+
+ u16 ss = s & 3;
+ u16 tt = t & 3;
+
+ int colorSel = dxtBlock->lines[tt];
+ int rs = 6 - (ss << 1);
+ colorSel = (colorSel >> rs) & 3;
+ colorSel |= c1 > c2?0:4;
+
+ u32 color = 0;
+
+ switch (colorSel)
+ {
+ case 0:
+ case 4:
+ color = makeRGBA(red1, green1, blue1, 255);
+ break;
+ case 1:
+ case 5:
+ color = makeRGBA(red2, green2, blue2, 255);
+ break;
+ case 2:
+ color = makeRGBA(red1+(red2-red1)/3, green1+(green2-green1)/3, blue1+(blue2-blue1)/3, 255);
+ break;
+ case 3:
+ color = makeRGBA(red2+(red1-red2)/3, green2+(green1-green2)/3, blue2+(blue1-blue2)/3, 255);
+ break;
+ case 6:
+ color = makeRGBA((int)ceil((float)(red1+red2)/2), (int)ceil((float)(green1+green2)/2), (int)ceil((float)(blue1+blue2)/2), 255);
+ break;
+ case 7:
+ color = makeRGBA(red2, green2, blue2, 0);
+ break;
+ }
+
+ *((u32*)dst) = color;
+ }
+ break;
+ }
+}
+
+
const char* texfmt[] = {
// pixel
"I4", "I8", "IA4", "IA8",