dolphin/Source/Plugins/Plugin_VideoSoftware/Src/TextureEncoder.cpp
donkopunchstania 8a711eadac Video software:
Changed the EFB color order from RGBA to ABGR to emulate it correctly on little-endian platforms. Added some enumerations to clear up what components are which colors. Fixed the TEV alpha input LUT which would have caused problems if anything was doing alpha comparisons.
Changed box filter for EFB copies from 3x3 to 2x2 because that is probably correct. Also makes the math nicer.


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6696 8ced0084-cf51-0410-be5f-012b33b47a6e
2010-12-31 06:45:18 +00:00

1435 lines
43 KiB
C++

// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "TextureEncoder.h"
#include "EfbInterface.h"
#include "../../../Core/VideoCommon/Src/LookUpTables.h"
#include "BPMemLoader.h"
#include "../../../Core/VideoCommon/Src/TextureDecoder.h"
namespace TextureEncoder
{
inline void RGBA_to_RGBA8(u8 *src, u8 &r, u8 &g, u8 &b, u8 &a)
{
u32 srcColor = *(u32*)src;
a = Convert6To8(srcColor & 0x3f);
b = Convert6To8((srcColor >> 6) & 0x3f);
g = Convert6To8((srcColor >> 12)& 0x3f);
r = Convert6To8((srcColor >> 18)& 0x3f);
}
inline void RGBA_to_RGB8(u8 *src, u8 &r, u8 &g, u8 &b)
{
u32 srcColor = *(u32*)src;
b = Convert6To8((srcColor >> 6) & 0x3f);
g = Convert6To8((srcColor >> 12)& 0x3f);
r = Convert6To8((srcColor >> 18)& 0x3f);
}
inline u8 RGB8_to_I(u8 r, u8 g, u8 b)
{
// values multiplied by 256 to keep math integer
u16 val = 4096 + 66 * r + 129 * g + 25 * b;
return val >> 8;
}
// box filter sampling averages 4 samples with the source texel being the top left of the box
// components are scaled to the range 0-255 after all samples are taken
inline void boxfilterRGBA_to_RGBA8(u8 *src, u8 &r, u8 &g, u8 &b, u8 &a)
{
u16 r16 = 0, g16 = 0, b16 = 0, a16 = 0;
for (int y = 0; y < 2; y++) {
for (int x = 0; x < 2; x++) {
u32 srcColor = *(u32*)src;
a16 += srcColor & 0x3f;
b16 += (srcColor >> 6) & 0x3f;
g16 += (srcColor >> 12) & 0x3f;
r16 += (srcColor >> 18) & 0x3f;
src += 3; // move to next pixel
}
src += (640 - 2) * 3; // move to next line
}
r = r16 + (r16 >> 6);
g = g16 + (g16 >> 6);
b = b16 + (b16 >> 6);
a = a16 + (a16 >> 6);
}
inline void boxfilterRGBA_to_RGB8(u8 *src, u8 &r, u8 &g, u8 &b)
{
u16 r16 = 0, g16 = 0, b16 = 0;
for (int y = 0; y < 2; y++) {
for (int x = 0; x < 2; x++) {
u32 srcColor = *(u32*)src;
b16 += (srcColor >> 6) & 0x3f;
g16 += (srcColor >> 12) & 0x3f;
r16 += (srcColor >> 18) & 0x3f;
src += 3; // move to next pixel
}
src += (640 - 2) * 3; // move to next line
}
r = r16 + (r16 >> 6);
g = g16 + (g16 >> 6);
b = b16 + (b16 >> 6);
}
inline void boxfilterRGBA_to_x8(u8 *src, u8 &x8, int shift)
{
u16 x16 = 0;
for (int y = 0; y < 2; y++) {
for (int x = 0; x < 2; x++) {
u32 srcColor = *(u32*)src;
x16 += (srcColor >> shift) & 0x3f;
src += 3; // move to next pixel
}
src += (640 - 2) * 3; // move to next line
}
x8 = x16 + (x16 >> 6);
}
inline void boxfilterRGBA_to_xx8(u8 *src, u8 &x1, u8 &x2, int shift1, int shift2)
{
u16 x16_1 = 0;
u16 x16_2 = 0;
for (int y = 0; y < 2; y++) {
for (int x = 0; x < 2; x++) {
u32 srcColor = *(u32*)src;
x16_1 += (srcColor >> shift1) & 0x3f;
x16_2 += (srcColor >> shift2) & 0x3f;
src += 3; // move to next pixel
}
src += (640 - 2) * 3; // move to next line
}
x1 = x16_1 + (x16_1 >> 6);
x2 = x16_2 + (x16_2 >> 6);
}
inline void boxfilterRGB_to_RGB8(u8 *src, u8 &r, u8 &g, u8 &b)
{
u16 r16 = 0, g16 = 0, b16 = 0;
for (int y = 0; y < 2; y++) {
for (int x = 0; x < 2; x++) {
b16 += src[0];
g16 += src[1];
r16 += src[2];
src += 3; // move to next pixel
}
src += (640 - 2) * 3; // move to next line
}
r = r16 >> 2;
g = g16 >> 2;
b = b16 >> 2;
}
inline void boxfilterRGB_to_x8(u8 *src, u8 &x8, int comp)
{
u16 x16 = 0;
for (int y = 0; y < 2; y++) {
for (int x = 0; x < 2; x++) {
x16 += src[comp];
src += 3; // move to next pixel
}
src += (640 - 2) * 3; // move to next line
}
x8 = x16 >> 2;
}
inline void boxfilterRGB_to_xx8(u8 *src, u8 &x1, u8 &x2, int comp1, int comp2)
{
u16 x16_1 = 0;
u16 x16_2 = 0;
for (int y = 0; y < 2; y++) {
for (int x = 0; x < 2; x++) {
x16_1 += src[comp1];
x16_2 += src[comp2];
src += 3; // move to next pixel
}
src += (640 - 2) * 3; // move to next line
}
x1 = x16_1 >> 2;
x2 = x16_2 >> 2;
}
void SetBlockDimensions(int blkWidthLog2, int blkHeightLog2, u16 &sBlkCount, u16 &tBlkCount, u16 &sBlkSize, u16 &tBlkSize)
{
// if half_scale is 1 then the size is cut in half
u32 width = bpmem.copyTexSrcWH.x >> bpmem.triggerEFBCopy.half_scale;
u32 height = bpmem.copyTexSrcWH.y >> bpmem.triggerEFBCopy.half_scale;
sBlkCount = (width >> blkWidthLog2) + 1;
tBlkCount = (height >> blkHeightLog2) + 1;
sBlkSize = 1 << blkWidthLog2;
tBlkSize = 1 << blkHeightLog2;
}
void SetSpans(int sBlkSize, int tBlkSize, s32 &tSpan, s32 &sBlkSpan, s32 &tBlkSpan, s32 &writeStride)
{
// width is 1 less than the number of pixels of width
u32 width = bpmem.copyTexSrcWH.x >> bpmem.triggerEFBCopy.half_scale;
u32 alignedWidth = (width + sBlkSize) & (~(sBlkSize-1));
u32 readStride = 3 << bpmem.triggerEFBCopy.half_scale;
tSpan = (640 - sBlkSize) * readStride; // bytes to advance src pointer after each row of texels in a block
sBlkSpan = ((-640 * tBlkSize) + sBlkSize) * readStride; // bytes to advance src pointer after each block
tBlkSpan = ((640 * tBlkSize) - alignedWidth) * readStride; // bytes to advance src pointer after each row of blocks
writeStride = bpmem.copyMipMapStrideChannels * 32;
}
#define ENCODE_LOOP_BLOCKS \
for (int tBlk = 0; tBlk < tBlkCount; tBlk++) { \
dst = dstBlockStart; \
for (int sBlk = 0; sBlk < sBlkCount; sBlk++) { \
for (int t = 0; t < tBlkSize; t++) { \
for (int s = 0; s < sBlkSize; s++) { \
#define ENCODE_LOOP_SPANS \
} \
src += tSpan; \
} \
src += sBlkSpan; \
} \
src += tBlkSpan; \
dstBlockStart += writeStride; \
} \
#define ENCODE_LOOP_SPANS2 \
} \
src += tSpan; \
} \
src += sBlkSpan; \
dst += 32; \
} \
src += tBlkSpan; \
dstBlockStart += writeStride; \
} \
void EncodeRGBA6(u8 *dst, u8 *src, u32 format)
{
u16 sBlkCount, tBlkCount, sBlkSize, tBlkSize;
s32 tSpan, sBlkSpan, tBlkSpan, writeStride;
u8 r, g, b, a;
u32 readStride = 3;
u8 *dstBlockStart = dst;
switch(format)
{
case GX_TF_I4:
SetBlockDimensions(3, 3, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
sBlkSize /= 2;
ENCODE_LOOP_BLOCKS
{
RGBA_to_RGB8(src, r, g, b);
src += readStride;
*dst = RGB8_to_I(r, g, b) & 0xf0;
RGBA_to_RGB8(src, r, g, b);
src += readStride;
*dst |= RGB8_to_I(r, g, b) >> 4;
dst++;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_I8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
RGBA_to_RGB8(src, r, g, b);
src += readStride;
*dst++ = RGB8_to_I(r, g, b);
}
ENCODE_LOOP_SPANS
break;
case GX_TF_IA4:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
RGBA_to_RGBA8(src, r, g, b, a);
src += readStride;
*dst++ = (a & 0xf0) | (RGB8_to_I(r, g, b) >> 4);
}
ENCODE_LOOP_SPANS
break;
case GX_TF_IA8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
RGBA_to_RGBA8(src, r, g, b, a);
src += readStride;
*dst++ = a;
*dst++ = RGB8_to_I(r, g, b);
}
ENCODE_LOOP_SPANS
break;
case GX_TF_RGB565:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
u32 srcColor = *(u32*)src;
src += readStride;
u16 val = ((srcColor >> 8) & 0xf800) | ((srcColor >> 7) & 0x07e0) | ((srcColor >> 7) & 0x001e);
*(u16*)dst = Common::swap16(val);
dst+=2;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_RGB5A3:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
u32 srcColor = *(u32*)src;
src += readStride;
u16 alpha = (srcColor << 9) & 0x7000;
u16 val;
if (alpha == 0x7000) // 555
val = 0x8000 | ((srcColor >> 9) & 0x7c00) | ((srcColor >> 8) & 0x03e0) | ((srcColor >> 7) & 0x001e);
else // 4443
val = alpha | ((srcColor >> 12) & 0x0f00) | ((srcColor >> 10) & 0x00f0) | ((srcColor >> 8) & 0x000f);
*(u16*)dst = Common::swap16(val);
dst+=2;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_RGBA8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
RGBA_to_RGBA8(src, dst[1], dst[32], dst[33], dst[0]);
src += readStride;
dst += 2;
}
ENCODE_LOOP_SPANS2
break;
case GX_CTF_R4:
SetBlockDimensions(3, 3, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
sBlkSize /= 2;
ENCODE_LOOP_BLOCKS
{
u32 srcColor = *(u32*)src;
src += readStride;
*dst = (srcColor >> 16) & 0xf0;
srcColor = *(u32*)src;
src += readStride;
*dst |= (srcColor >> 20) & 0x0f;
dst++;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_RA4:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
u32 srcColor = *(u32*)src;
src += readStride;
*dst++ = ((srcColor << 2) & 0xf0) | ((srcColor >> 20) & 0x0f);
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_RA8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
u32 srcColor = *(u32*)src;
src += readStride;
*dst++ = Convert6To8(srcColor & 0x3f);
*dst++ = Convert6To8((srcColor >> 18) & 0x3f);
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_A8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
u32 srcColor = *(u32*)src;
*dst++ = Convert6To8(srcColor & 0x3f);
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_R8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
u32 srcColor = *(u32*)src;
*dst++ = Convert6To8((srcColor >> 18) & 0x3f);
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_G8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
u32 srcColor = *(u32*)src;
*dst++ = Convert6To8((srcColor >> 12) & 0x3f);
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_B8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
u32 srcColor = *(u32*)src;
*dst++ = Convert6To8((srcColor >> 6) & 0x3f);
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_RG8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
u32 srcColor = *(u32*)src;
src += readStride;
*dst++ = Convert6To8((srcColor >> 12) & 0x3f);
*dst++ = Convert6To8((srcColor >> 18) & 0x3f);
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_GB8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
u32 srcColor = *(u32*)src;
src += readStride;
*dst++ = Convert6To8((srcColor >> 6) & 0x3f);
*dst++ = Convert6To8((srcColor >> 12) & 0x3f);
}
ENCODE_LOOP_SPANS
break;
default:
PanicAlert("Unknown texture copy format: 0x%x\n", format);
break;
}
}
void EncodeRGBA6halfscale(u8 *dst, u8 *src, u32 format)
{
u16 sBlkCount, tBlkCount, sBlkSize, tBlkSize;
s32 tSpan, sBlkSpan, tBlkSpan, writeStride;
u8 r, g, b, a;
u32 readStride = 6;
u8 *dstBlockStart = dst;
switch(format)
{
case GX_TF_I4:
SetBlockDimensions(3, 3, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
sBlkSize /= 2;
ENCODE_LOOP_BLOCKS
{
boxfilterRGBA_to_RGB8(src, r, g, b);
src += readStride;
*dst = RGB8_to_I(r, g, b) & 0xf0;
boxfilterRGBA_to_RGB8(src, r, g, b);
src += readStride;
*dst |= RGB8_to_I(r, g, b) >> 4;
dst++;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_I8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGBA_to_RGB8(src, r, g, b);
src += readStride;
*dst++ = RGB8_to_I(r, g, b);
}
ENCODE_LOOP_SPANS
break;
case GX_TF_IA4:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGBA_to_RGBA8(src, r, g, b, a);
src += readStride;
*dst++ = (a & 0xf0) | (RGB8_to_I(r, g, b) >> 4);
}
ENCODE_LOOP_SPANS
break;
case GX_TF_IA8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGBA_to_RGBA8(src, r, g, b, a);
src += readStride;
*dst++ = a;
*dst++ = RGB8_to_I(r, g, b);
}
ENCODE_LOOP_SPANS
break;
case GX_TF_RGB565:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGBA_to_RGB8(src, r, g, b);
src += readStride;
u16 val = ((r << 8) & 0xf800) | ((g << 3) & 0x07e0) | ((b >> 3) & 0x001e);
*(u16*)dst = Common::swap16(val);
dst+=2;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_RGB5A3:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGBA_to_RGBA8(src, r, g, b, a);
src += readStride;
u16 val;
if (a >= 224) // 5551
val = 0x8000 | ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001e);
else // 4443
val = ((a << 7) & 0x7000) | ((r << 4) & 0x0f00) | (g & 0x00f0) | ((b >> 4) & 0x000f);
*(u16*)dst = Common::swap16(val);
dst+=2;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_RGBA8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGBA_to_RGBA8(src, dst[1], dst[32], dst[33], dst[0]);
src += readStride;
dst += 2;
}
ENCODE_LOOP_SPANS2
break;
case GX_CTF_R4:
SetBlockDimensions(3, 3, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
sBlkSize /= 2;
ENCODE_LOOP_BLOCKS
{
boxfilterRGBA_to_x8(src, r, 18);
src += readStride;
*dst = r & 0xf0;
boxfilterRGBA_to_x8(src, r, 18);
src += readStride;
*dst |= r >> 4;
dst++;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_RA4:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGBA_to_xx8(src, r, a, 18, 0);
src += readStride;
*dst++ = (a & 0xf0) | (r >> 4);
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_RA8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGBA_to_xx8(src, r, a, 18, 0);
src += readStride;
*dst++ = a;
*dst++ = r;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_A8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGBA_to_x8(src, a, 0);
*dst++ = a;
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_R8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGBA_to_x8(src, r, 18);
*dst++ = r;
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_G8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGBA_to_x8(src, g, 12);
*dst++ = g;
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_B8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGBA_to_x8(src, b, 6);
*dst++ = b;
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_RG8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGBA_to_xx8(src, r, g, 18, 12);
src += readStride;
*dst++ = g;
*dst++ = r;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_GB8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGBA_to_xx8(src, g, b, 12, 6);
src += readStride;
*dst++ = b;
*dst++ = g;
}
ENCODE_LOOP_SPANS
break;
default:
PanicAlert("Unknown texture copy format: 0x%x\n", format);
break;
}
}
void EncodeRGB8(u8 *dst, u8 *src, u32 format)
{
u16 sBlkCount, tBlkCount, sBlkSize, tBlkSize;
s32 tSpan, sBlkSpan, tBlkSpan, writeStride;
u32 readStride = 3;
u8 *dstBlockStart = dst;
switch(format)
{
case GX_TF_I4:
SetBlockDimensions(3, 3, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
sBlkSize /= 2;
ENCODE_LOOP_BLOCKS
{
*dst = RGB8_to_I(src[2], src[1], src[0]) & 0xf0;
src += readStride;
*dst |= RGB8_to_I(src[2], src[1], src[0]) >> 4;
src += readStride;
dst++;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_I8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
*dst++ = RGB8_to_I(src[2], src[1], src[0]);
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_IA4:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
*dst++ = 0xf0 | (RGB8_to_I(src[2], src[1], src[0]) >> 4);
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_IA8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
*dst++ = 0xff;
*dst++ = RGB8_to_I(src[2], src[1], src[0]);
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_RGB565:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
u16 val = ((src[2] << 8) & 0xf800) | ((src[1] << 3) & 0x07e0) | ((src[0] >> 3) & 0x001e);
*(u16*)dst = Common::swap16(val);
src += readStride;
dst+=2;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_RGB5A3:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
u16 val = 0x8000 | ((src[2] << 7) & 0x7c00) | ((src[1] << 2) & 0x03e0) | ((src[0] >> 3) & 0x001e);
*(u16*)dst = Common::swap16(val);
src += readStride;
dst+=2;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_RGBA8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
dst[0] = 0xff;
dst[1] = src[2];
dst[32] = src[1];
dst[33] = src[0];
src += readStride;
dst += 2;
}
ENCODE_LOOP_SPANS2
break;
case GX_CTF_R4:
SetBlockDimensions(3, 3, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
sBlkSize /= 2;
ENCODE_LOOP_BLOCKS
{
*dst = src[2] & 0xf0;
src += readStride;
*dst |= src[2] >> 4;
src += readStride;
dst++;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_RA4:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
*dst++ = 0xf0 | (src[2] >> 4);
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_RA8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
*dst++ = 0xff;
*dst++ = src[2];
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_A8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
*dst++ = 0xff;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_R8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
*dst++ = src[2];
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_G8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
*dst++ = src[1];
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_B8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
*dst++ = src[0];
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_RG8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
*dst++ = src[1];
*dst++ = src[2];
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_GB8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
*dst++ = src[0];
*dst++ = src[1];
src += readStride;
}
ENCODE_LOOP_SPANS
break;
default:
PanicAlert("Unknown texture copy format: 0x%x\n", format);
break;
}
}
void EncodeRGB8halfscale(u8 *dst, u8 *src, u32 format)
{
u16 sBlkCount, tBlkCount, sBlkSize, tBlkSize;
s32 tSpan, sBlkSpan, tBlkSpan, writeStride;
u8 r, g, b;
u32 readStride = 6;
u8 *dstBlockStart = dst;
switch(format)
{
case GX_TF_I4:
SetBlockDimensions(3, 3, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
sBlkSize /= 2;
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_RGB8(src, r, g, b);
*dst = RGB8_to_I(r, g, b) & 0xf0;
src += readStride;
boxfilterRGB_to_RGB8(src, r, g, b);
*dst |= RGB8_to_I(r, g, b) >> 4;
src += readStride;
dst++;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_I8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_RGB8(src, r, g, b);
*dst++ = RGB8_to_I(r, g, b);
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_IA4:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_RGB8(src, r, g, b);
*dst++ = 0xf0 | (RGB8_to_I(r, g, b) >> 4);
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_IA8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_RGB8(src, r, g, b);
*dst++ = 0xff;
*dst++ = RGB8_to_I(r, g, b);
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_RGB565:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_RGB8(src, r, g, b);
u16 val = ((r << 8) & 0xf800) | ((g << 3) & 0x07e0) | ((b >> 3) & 0x001e);
*(u16*)dst = Common::swap16(val);
src += readStride;
dst+=2;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_RGB5A3:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_RGB8(src, r, g, b);
u16 val = 0x8000 | ((r << 7) & 0x7c00) | ((g << 2) & 0x03e0) | ((b >> 3) & 0x001e);
*(u16*)dst = Common::swap16(val);
src += readStride;
dst+=2;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_RGBA8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_RGB8(src, r, g, b);
dst[0] = 0xff;
dst[1] = r;
dst[32] = g;
dst[33] = b;
src += readStride;
dst += 2;
}
ENCODE_LOOP_SPANS2
break;
case GX_CTF_R4:
SetBlockDimensions(3, 3, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
sBlkSize /= 2;
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_x8(src, r, 2);
*dst = r & 0xf0;
src += readStride;
boxfilterRGB_to_x8(src, r, 2);
*dst |= r >> 4;
src += readStride;
dst++;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_RA4:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_x8(src, r, 2);
*dst++ = 0xf0 | (r >> 4);
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_RA8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_x8(src, r, 2);
*dst++ = 0xff;
*dst++ = r;
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_A8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
*dst++ = 0xff;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_R8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_x8(src, r, 2);
*dst++ = r;
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_G8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_x8(src, g, 1);
*dst++ = g;
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_B8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_x8(src, b, 0);
*dst++ = b;
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_RG8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_xx8(src, r, g, 2, 1);
*dst++ = g;
*dst++ = r;
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_GB8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_xx8(src, g, b, 1, 0);
*dst++ = b;
*dst++ = g;
src += readStride;
}
ENCODE_LOOP_SPANS
break;
default:
PanicAlert("Unknown texture copy format: 0x%x\n", format);
break;
}
}
void EncodeZ24(u8 *dst, u8 *src, u32 format)
{
u16 sBlkCount, tBlkCount, sBlkSize, tBlkSize;
s32 tSpan, sBlkSpan, tBlkSpan, writeStride;
u32 readStride = 3;
u8 *dstBlockStart = dst;
switch(format)
{
case GX_TF_Z8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
*dst++ = src[2];
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_Z16:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
*dst++ = src[1];
*dst++ = src[2];
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_Z24X8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
dst[0] = 0xff;
dst[1] = src[2];
dst[32] = src[1];
dst[33] = src[0];
src += readStride;
dst += 2;
}
ENCODE_LOOP_SPANS2
break;
case GX_CTF_Z4:
SetBlockDimensions(3, 3, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
sBlkSize /= 2;
ENCODE_LOOP_BLOCKS
{
*dst = src[2] & 0xf0;
src += readStride;
*dst |= src[2] >> 4;
src += readStride;
dst++;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_Z8M:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
*dst++ = src[1];
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_Z8L:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
*dst++ = src[0];
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_Z16L:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
*dst++ = src[0];
*dst++ = src[1];
src += readStride;
}
ENCODE_LOOP_SPANS
break;
default:
PanicAlert("Unknown texture copy format: 0x%x\n", format);
break;
}
}
void EncodeZ24halfscale(u8 *dst, u8 *src, u32 format)
{
u16 sBlkCount, tBlkCount, sBlkSize, tBlkSize;
s32 tSpan, sBlkSpan, tBlkSpan, writeStride;
u32 readStride = 6;
u8 r, g, b;
u8 *dstBlockStart = dst;
switch(format)
{
case GX_TF_Z8:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_x8(src, b, 2);
*dst++ = b;
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_Z16:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_xx8(src, g, b, 1, 2);
*dst++ = b;
*dst++ = g;
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_TF_Z24X8:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_RGB8(src, dst[33], dst[32], dst[1]);
dst[0] = 255;
src += readStride;
dst += 2;
}
ENCODE_LOOP_SPANS2
break;
case GX_CTF_Z4:
SetBlockDimensions(3, 3, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
sBlkSize /= 2;
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_x8(src, b, 2);
*dst = b & 0xf0;
src += readStride;
boxfilterRGB_to_x8(src, b, 2);
*dst |= b >> 4;
src += readStride;
dst++;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_Z8M:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_x8(src, g, 1);
*dst++ = g;
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_Z8L:
SetBlockDimensions(3, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_x8(src, r, 0);
*dst++ = r;
src += readStride;
}
ENCODE_LOOP_SPANS
break;
case GX_CTF_Z16L:
SetBlockDimensions(2, 2, sBlkCount, tBlkCount, sBlkSize, tBlkSize);
SetSpans(sBlkSize, tBlkSize, tSpan, sBlkSpan, tBlkSpan, writeStride);
ENCODE_LOOP_BLOCKS
{
boxfilterRGB_to_xx8(src, r, g, 0, 1);
*dst++ = g;
*dst++ = r;
src += readStride;
}
ENCODE_LOOP_SPANS
break;
default:
PanicAlert("Unknown texture copy format: 0x%x\n", format);
break;
}
}
void Encode(u8 *dest_ptr)
{
int pixelformat = bpmem.zcontrol.pixel_format;
bool bFromZBuffer = pixelformat == PIXELFMT_Z24;
bool bIsIntensityFmt = bpmem.triggerEFBCopy.intensity_fmt > 0;
u32 copyfmt = ((bpmem.triggerEFBCopy.target_pixel_format / 2) + ((bpmem.triggerEFBCopy.target_pixel_format & 1) * 8));
// pack copy format information into a single variable
u32 format = copyfmt;
if (bFromZBuffer)
{
format |= _GX_TF_ZTF;
if (copyfmt == 11)
format = GX_TF_Z16;
else if (format < GX_TF_Z8 || format > GX_TF_Z24X8)
format |= _GX_TF_CTF;
}
else
if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt))
format |= _GX_TF_CTF;
u8 *src = EfbInterface::GetPixelPointer(bpmem.copyTexSrcXY.x, bpmem.copyTexSrcXY.y, bFromZBuffer);
if (bpmem.triggerEFBCopy.half_scale)
{
if (pixelformat == PIXELFMT_RGBA6_Z24)
EncodeRGBA6halfscale(dest_ptr, src, format);
else if (pixelformat == PIXELFMT_RGB8_Z24)
EncodeRGB8halfscale(dest_ptr, src, format);
else if (pixelformat == PIXELFMT_RGB565_Z16) // not supported
EncodeRGB8halfscale(dest_ptr, src, format);
else if (pixelformat == PIXELFMT_Z24)
EncodeZ24halfscale(dest_ptr, src, format);
}
else
{
if (pixelformat == PIXELFMT_RGBA6_Z24)
EncodeRGBA6(dest_ptr, src, format);
else if (pixelformat == PIXELFMT_RGB8_Z24)
EncodeRGB8(dest_ptr, src, format);
else if (pixelformat == PIXELFMT_RGB565_Z16) // not supported
EncodeRGB8(dest_ptr, src, format);
else if (pixelformat == PIXELFMT_Z24)
EncodeZ24(dest_ptr, src, format);
}
}
}