mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 22:09:19 -07:00
8a711eadac
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
1436 lines
43 KiB
C++
1436 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);
|
|
}
|
|
}
|
|
|
|
|
|
}
|