📄 texcompress_fxt1.c
字号:
for (j = 2 * 2 - 1; j >= 0; j--) {
for (i = 0; i < n_comp; i++) {
/* add in colors */
FX64_SHL(hi, 5);
FX64_OR32(hi, vec[j][i] >> 3);
}
}
((Fx64 *)cc)[1] = hi;
}
static void
fxt1_quantize (GLuint *cc, const GLubyte *lines[], GLint comps)
{
GLint trualpha;
GLubyte reord[N_TEXELS][MAX_COMP];
GLubyte input[N_TEXELS][MAX_COMP];
GLint i, k, l;
if (comps == 3) {
/* make the whole block opaque */
memset(input, -1, sizeof(input));
}
/* 8 texels each line */
for (l = 0; l < 4; l++) {
for (k = 0; k < 4; k++) {
for (i = 0; i < comps; i++) {
input[k + l * 4][i] = *lines[l]++;
}
}
for (; k < 8; k++) {
for (i = 0; i < comps; i++) {
input[k + l * 4 + 12][i] = *lines[l]++;
}
}
}
/* block layout:
* 00, 01, 02, 03, 08, 09, 0a, 0b
* 10, 11, 12, 13, 18, 19, 1a, 1b
* 04, 05, 06, 07, 0c, 0d, 0e, 0f
* 14, 15, 16, 17, 1c, 1d, 1e, 1f
*/
/* [dBorca]
* stupidity flows forth from this
*/
l = N_TEXELS;
trualpha = 0;
if (comps == 4) {
/* skip all transparent black texels */
l = 0;
for (k = 0; k < N_TEXELS; k++) {
/* test all components against 0 */
if (!ISTBLACK(input[k])) {
/* texel is not transparent black */
COPY_4UBV(reord[l], input[k]);
if (reord[l][ACOMP] < (255 - ALPHA_TS)) {
/* non-opaque texel */
trualpha = !0;
}
l++;
}
}
}
#if 0
if (trualpha) {
fxt1_quantize_ALPHA0(cc, input, reord, l);
} else if (l == 0) {
cc[0] = cc[1] = cc[2] = -1;
cc[3] = 0;
} else if (l < N_TEXELS) {
fxt1_quantize_HI(cc, input, reord, l);
} else {
fxt1_quantize_CHROMA(cc, input);
}
(void)fxt1_quantize_ALPHA1;
(void)fxt1_quantize_MIXED1;
(void)fxt1_quantize_MIXED0;
#else
if (trualpha) {
fxt1_quantize_ALPHA1(cc, input);
} else if (l == 0) {
cc[0] = cc[1] = cc[2] = ~0u;
cc[3] = 0;
} else if (l < N_TEXELS) {
fxt1_quantize_MIXED1(cc, input);
} else {
fxt1_quantize_MIXED0(cc, input);
}
(void)fxt1_quantize_ALPHA0;
(void)fxt1_quantize_HI;
(void)fxt1_quantize_CHROMA;
#endif
}
static GLint
fxt1_encode (GLuint width, GLuint height, GLint comps,
const void *source, GLint srcRowStride,
void *dest, GLint destRowStride)
{
GLuint x, y;
const GLubyte *data;
GLuint *encoded = (GLuint *)dest;
GLubyte *newSource = NULL;
/* Replicate image if width is not M8 or height is not M4 */
if ((width & 7) | (height & 3)) {
GLint newWidth = (width + 7) & ~7;
GLint newHeight = (height + 3) & ~3;
newSource = (GLubyte *)
_mesa_malloc(comps * newWidth * newHeight * sizeof(GLubyte *));
_mesa_upscale_teximage2d(width, height, newWidth, newHeight,
comps, (const GLchan *) source,
srcRowStride, newSource);
source = newSource;
width = newWidth;
height = newHeight;
srcRowStride = comps * newWidth;
}
data = (const GLubyte *) source;
destRowStride = (destRowStride - width * 2) / 4;
for (y = 0; y < height; y += 4) {
GLuint offs = 0 + (y + 0) * srcRowStride;
for (x = 0; x < width; x += 8) {
const GLubyte *lines[4];
lines[0] = &data[offs];
lines[1] = lines[0] + srcRowStride;
lines[2] = lines[1] + srcRowStride;
lines[3] = lines[2] + srcRowStride;
offs += 8 * comps;
fxt1_quantize(encoded, lines, comps);
/* 128 bits per 8x4 block */
encoded += 4;
}
encoded += destRowStride;
}
if (newSource != NULL) {
_mesa_free(newSource);
}
return 0;
}
/***************************************************************************\
* FXT1 decoder
*
* The decoder is based on GL_3DFX_texture_compression_FXT1
* specification and serves as a concept for the encoder.
\***************************************************************************/
/* lookup table for scaling 5 bit colors up to 8 bits */
static const GLubyte _rgb_scale_5[] = {
0, 8, 16, 25, 33, 41, 49, 58,
66, 74, 82, 90, 99, 107, 115, 123,
132, 140, 148, 156, 165, 173, 181, 189,
197, 206, 214, 222, 230, 239, 247, 255
};
/* lookup table for scaling 6 bit colors up to 8 bits */
static const GLubyte _rgb_scale_6[] = {
0, 4, 8, 12, 16, 20, 24, 28,
32, 36, 40, 45, 49, 53, 57, 61,
65, 69, 73, 77, 81, 85, 89, 93,
97, 101, 105, 109, 113, 117, 121, 125,
130, 134, 138, 142, 146, 150, 154, 158,
162, 166, 170, 174, 178, 182, 186, 190,
194, 198, 202, 206, 210, 215, 219, 223,
227, 231, 235, 239, 243, 247, 251, 255
};
#define CC_SEL(cc, which) (((GLuint *)(cc))[(which) / 32] >> ((which) & 31))
#define UP5(c) _rgb_scale_5[(c) & 31]
#define UP6(c, b) _rgb_scale_6[(((c) & 31) << 1) | ((b) & 1)]
#define LERP(n, t, c0, c1) (((n) - (t)) * (c0) + (t) * (c1) + (n) / 2) / (n)
#define ZERO_4UBV(v) *((GLuint *)(v)) = 0
static void
fxt1_decode_1HI (const GLubyte *code, GLint t, GLubyte *rgba)
{
const GLuint *cc;
t *= 3;
cc = (const GLuint *)(code + t / 8);
t = (cc[0] >> (t & 7)) & 7;
if (t == 7) {
ZERO_4UBV(rgba);
} else {
cc = (const GLuint *)(code + 12);
if (t == 0) {
rgba[BCOMP] = UP5(CC_SEL(cc, 0));
rgba[GCOMP] = UP5(CC_SEL(cc, 5));
rgba[RCOMP] = UP5(CC_SEL(cc, 10));
} else if (t == 6) {
rgba[BCOMP] = UP5(CC_SEL(cc, 15));
rgba[GCOMP] = UP5(CC_SEL(cc, 20));
rgba[RCOMP] = UP5(CC_SEL(cc, 25));
} else {
rgba[BCOMP] = LERP(6, t, UP5(CC_SEL(cc, 0)), UP5(CC_SEL(cc, 15)));
rgba[GCOMP] = LERP(6, t, UP5(CC_SEL(cc, 5)), UP5(CC_SEL(cc, 20)));
rgba[RCOMP] = LERP(6, t, UP5(CC_SEL(cc, 10)), UP5(CC_SEL(cc, 25)));
}
rgba[ACOMP] = 255;
}
}
static void
fxt1_decode_1CHROMA (const GLubyte *code, GLint t, GLubyte *rgba)
{
const GLuint *cc;
GLuint kk;
cc = (const GLuint *)code;
if (t & 16) {
cc++;
t &= 15;
}
t = (cc[0] >> (t * 2)) & 3;
t *= 15;
cc = (const GLuint *)(code + 8 + t / 8);
kk = cc[0] >> (t & 7);
rgba[BCOMP] = UP5(kk);
rgba[GCOMP] = UP5(kk >> 5);
rgba[RCOMP] = UP5(kk >> 10);
rgba[ACOMP] = 255;
}
static void
fxt1_decode_1MIXED (const GLubyte *code, GLint t, GLubyte *rgba)
{
const GLuint *cc;
GLuint col[2][3];
GLint glsb, selb;
cc = (const GLuint *)code;
if (t & 16) {
t &= 15;
t = (cc[1] >> (t * 2)) & 3;
/* col 2 */
col[0][BCOMP] = (*(const GLuint *)(code + 11)) >> 6;
col[0][GCOMP] = CC_SEL(cc, 99);
col[0][RCOMP] = CC_SEL(cc, 104);
/* col 3 */
col[1][BCOMP] = CC_SEL(cc, 109);
col[1][GCOMP] = CC_SEL(cc, 114);
col[1][RCOMP] = CC_SEL(cc, 119);
glsb = CC_SEL(cc, 126);
selb = CC_SEL(cc, 33);
} else {
t = (cc[0] >> (t * 2)) & 3;
/* col 0 */
col[0][BCOMP] = CC_SEL(cc, 64);
col[0][GCOMP] = CC_SEL(cc, 69);
col[0][RCOMP] = CC_SEL(cc, 74);
/* col 1 */
col[1][BCOMP] = CC_SEL(cc, 79);
col[1][GCOMP] = CC_SEL(cc, 84);
col[1][RCOMP] = CC_SEL(cc, 89);
glsb = CC_SEL(cc, 125);
selb = CC_SEL(cc, 1);
}
if (CC_SEL(cc, 124) & 1) {
/* alpha[0] == 1 */
if (t == 3) {
ZERO_4UBV(rgba);
} else {
if (t == 0) {
rgba[BCOMP] = UP5(col[0][BCOMP]);
rgba[GCOMP] = UP5(col[0][GCOMP]);
rgba[RCOMP] = UP5(col[0][RCOMP]);
} else if (t == 2) {
rgba[BCOMP] = UP5(col[1][BCOMP]);
rgba[GCOMP] = UP6(col[1][GCOMP], glsb);
rgba[RCOMP] = UP5(col[1][RCOMP]);
} else {
rgba[BCOMP] = (UP5(col[0][BCOMP]) + UP5(col[1][BCOMP])) / 2;
rgba[GCOMP] = (UP5(col[0][GCOMP]) + UP6(col[1][GCOMP], glsb)) / 2;
rgba[RCOMP] = (UP5(col[0][RCOMP]) + UP5(col[1][RCOMP])) / 2;
}
rgba[ACOMP] = 255;
}
} else {
/* alpha[0] == 0 */
if (t == 0) {
rgba[BCOMP] = UP5(col[0][BCOMP]);
rgba[GCOMP] = UP6(col[0][GCOMP], glsb ^ selb);
rgba[RCOMP] = UP5(col[0][RCOMP]);
} else if (t == 3) {
rgba[BCOMP] = UP5(col[1][BCOMP]);
rgba[GCOMP] = UP6(col[1][GCOMP], glsb);
rgba[RCOMP] = UP5(col[1][RCOMP]);
} else {
rgba[BCOMP] = LERP(3, t, UP5(col[0][BCOMP]), UP5(col[1][BCOMP]));
rgba[GCOMP] = LERP(3, t, UP6(col[0][GCOMP], glsb ^ selb),
UP6(col[1][GCOMP], glsb));
rgba[RCOMP] = LERP(3, t, UP5(col[0][RCOMP]), UP5(col[1][RCOMP]));
}
rgba[ACOMP] = 255;
}
}
static void
fxt1_decode_1ALPHA (const GLubyte *code, GLint t, GLubyte *rgba)
{
const GLuint *cc;
cc = (const GLuint *)code;
if (CC_SEL(cc, 124) & 1) {
/* lerp == 1 */
GLuint col0[4];
if (t & 16) {
t &= 15;
t = (cc[1] >> (t * 2)) & 3;
/* col 2 */
col0[BCOMP] = (*(const GLuint *)(code + 11)) >> 6;
col0[GCOMP] = CC_SEL(cc, 99);
col0[RCOMP] = CC_SEL(cc, 104);
col0[ACOMP] = CC_SEL(cc, 119);
} else {
t = (cc[0] >> (t * 2)) & 3;
/* col 0 */
col0[BCOMP] = CC_SEL(cc, 64);
col0[GCOMP] = CC_SEL(cc, 69);
col0[RCOMP] = CC_SEL(cc, 74);
col0[ACOMP] = CC_SEL(cc, 109);
}
if (t == 0) {
rgba[BCOMP] = UP5(col0[BCOMP]);
rgba[GCOMP] = UP5(col0[GCOMP]);
rgba[RCOMP] = UP5(col0[RCOMP]);
rgba[ACOMP] = UP5(col0[ACOMP]);
} else if (t == 3) {
rgba[BCOMP] = UP5(CC_SEL(cc, 79));
rgba[GCOMP] = UP5(CC_SEL(cc, 84));
rgba[RCOMP] = UP5(CC_SEL(cc, 89));
rgba[ACOMP] = UP5(CC_SEL(cc, 114));
} else {
rgba[BCOMP] = LERP(3, t, UP5(col0[BCOMP]), UP5(CC_SEL(cc, 79)));
rgba[GCOMP] = LERP(3, t, UP5(col0[GCOMP]), UP5(CC_SEL(cc, 84)));
rgba[RCOMP] = LERP(3, t, UP5(col0[RCOMP]), UP5(CC_SEL(cc, 89)));
rgba[ACOMP] = LERP(3, t, UP5(col0[ACOMP]), UP5(CC_SEL(cc, 114)));
}
} else {
/* lerp == 0 */
if (t & 16) {
cc++;
t &= 15;
}
t = (cc[0] >> (t * 2)) & 3;
if (t == 3) {
ZERO_4UBV(rgba);
} else {
GLuint kk;
cc = (const GLuint *)code;
rgba[ACOMP] = UP5(cc[3] >> (t * 5 + 13));
t *= 15;
cc = (const GLuint *)(code + 8 + t / 8);
kk = cc[0] >> (t & 7);
rgba[BCOMP] = UP5(kk);
rgba[GCOMP] = UP5(kk >> 5);
rgba[RCOMP] = UP5(kk >> 10);
}
}
}
void
fxt1_decode_1 (const void *texture, GLint stride, /* in pixels */
GLint i, GLint j, GLubyte *rgba)
{
static void (*decode_1[]) (const GLubyte *, GLint, GLubyte *) = {
fxt1_decode_1HI, /* cc-high = "00?" */
fxt1_decode_1HI, /* cc-high = "00?" */
fxt1_decode_1CHROMA, /* cc-chroma = "010" */
fxt1_decode_1ALPHA, /* alpha = "011" */
fxt1_decode_1MIXED, /* mixed = "1??" */
fxt1_decode_1MIXED, /* mixed = "1??" */
fxt1_decode_1MIXED, /* mixed = "1??" */
fxt1_decode_1MIXED /* mixed = "1??" */
};
const GLubyte *code = (const GLubyte *)texture +
((j / 4) * (stride / 8) + (i / 8)) * 16;
GLint mode = CC_SEL(code, 125);
GLint t = i & 7;
if (t & 4) {
t += 12;
}
t += (j & 3) * 4;
decode_1[mode](code, t, rgba);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -