📄 texcompress_fxt1.c
字号:
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 voidfxt1_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; void *newSource = NULL; assert(comps == 3 || comps == 4); /* 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 = _mesa_malloc(comps * newWidth * newHeight * sizeof(GLchan)); if (!newSource) { GET_CURRENT_CONTEXT(ctx); _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture compression"); goto cleanUp; } _mesa_upscale_teximage2d(width, height, newWidth, newHeight, comps, (const GLchan *) source, srcRowStride, (GLchan *) newSource); source = newSource; width = newWidth; height = newHeight; srcRowStride = comps * newWidth; } /* convert from 16/32-bit channels to GLubyte if needed */ if (CHAN_TYPE != GL_UNSIGNED_BYTE) { const GLuint n = width * height * comps; const GLchan *src = (const GLchan *) source; GLubyte *dest = (GLubyte *) _mesa_malloc(n * sizeof(GLubyte)); GLuint i; if (!dest) { GET_CURRENT_CONTEXT(ctx); _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture compression"); goto cleanUp; } for (i = 0; i < n; i++) { dest[i] = CHAN_TO_UBYTE(src[i]); } if (newSource != NULL) { _mesa_free(newSource); } newSource = dest; /* we'll free this buffer before returning */ source = dest; /* the new, GLubyte incoming image */ } 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; } cleanUp: if (newSource != NULL) { _mesa_free(newSource); }}/***************************************************************************\ * 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)static voidfxt1_decode_1HI (const GLubyte *code, GLint t, GLchan *rgba){ const GLuint *cc; t *= 3; cc = (const GLuint *)(code + t / 8); t = (cc[0] >> (t & 7)) & 7; if (t == 7) { rgba[RCOMP] = rgba[GCOMP] = rgba[BCOMP] = rgba[ACOMP] = 0; } else { GLubyte r, g, b; cc = (const GLuint *)(code + 12); if (t == 0) { b = UP5(CC_SEL(cc, 0)); g = UP5(CC_SEL(cc, 5)); r = UP5(CC_SEL(cc, 10)); } else if (t == 6) { b = UP5(CC_SEL(cc, 15)); g = UP5(CC_SEL(cc, 20)); r = UP5(CC_SEL(cc, 25)); } else { b = LERP(6, t, UP5(CC_SEL(cc, 0)), UP5(CC_SEL(cc, 15))); g = LERP(6, t, UP5(CC_SEL(cc, 5)), UP5(CC_SEL(cc, 20))); r = LERP(6, t, UP5(CC_SEL(cc, 10)), UP5(CC_SEL(cc, 25))); } rgba[RCOMP] = UBYTE_TO_CHAN(r); rgba[GCOMP] = UBYTE_TO_CHAN(g); rgba[BCOMP] = UBYTE_TO_CHAN(b); rgba[ACOMP] = CHAN_MAX; }}static voidfxt1_decode_1CHROMA (const GLubyte *code, GLint t, GLchan *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] = UBYTE_TO_CHAN( UP5(kk) ); rgba[GCOMP] = UBYTE_TO_CHAN( UP5(kk >> 5) ); rgba[RCOMP] = UBYTE_TO_CHAN( UP5(kk >> 10) ); rgba[ACOMP] = CHAN_MAX;}static voidfxt1_decode_1MIXED (const GLubyte *code, GLint t, GLchan *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 */ rgba[RCOMP] = rgba[BCOMP] = rgba[GCOMP] = rgba[ACOMP] = 0; } else { GLubyte r, g, b; if (t == 0) { b = UP5(col[0][BCOMP]); g = UP5(col[0][GCOMP]); r = UP5(col[0][RCOMP]); } else if (t == 2) { b = UP5(col[1][BCOMP]); g = UP6(col[1][GCOMP], glsb); r = UP5(col[1][RCOMP]); } else { b = (UP5(col[0][BCOMP]) + UP5(col[1][BCOMP])) / 2; g = (UP5(col[0][GCOMP]) + UP6(col[1][GCOMP], glsb)) / 2; r = (UP5(col[0][RCOMP]) + UP5(col[1][RCOMP])) / 2; } rgba[RCOMP] = UBYTE_TO_CHAN(r); rgba[GCOMP] = UBYTE_TO_CHAN(g); rgba[BCOMP] = UBYTE_TO_CHAN(b); rgba[ACOMP] = CHAN_MAX; } } else { /* alpha[0] == 0 */ GLubyte r, g, b; if (t == 0) { b = UP5(col[0][BCOMP]); g = UP6(col[0][GCOMP], glsb ^ selb); r = UP5(col[0][RCOMP]); } else if (t == 3) { b = UP5(col[1][BCOMP]); g = UP6(col[1][GCOMP], glsb); r = UP5(col[1][RCOMP]); } else { b = LERP(3, t, UP5(col[0][BCOMP]), UP5(col[1][BCOMP])); g = LERP(3, t, UP6(col[0][GCOMP], glsb ^ selb), UP6(col[1][GCOMP], glsb)); r = LERP(3, t, UP5(col[0][RCOMP]), UP5(col[1][RCOMP])); } rgba[RCOMP] = UBYTE_TO_CHAN(r); rgba[GCOMP] = UBYTE_TO_CHAN(g); rgba[BCOMP] = UBYTE_TO_CHAN(b); rgba[ACOMP] = CHAN_MAX; }}static voidfxt1_decode_1ALPHA (const GLubyte *code, GLint t, GLchan *rgba){ const GLuint *cc; GLubyte r, g, b, a; 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) { b = UP5(col0[BCOMP]); g = UP5(col0[GCOMP]); r = UP5(col0[RCOMP]); a = UP5(col0[ACOMP]); } else if (t == 3) { b = UP5(CC_SEL(cc, 79)); g = UP5(CC_SEL(cc, 84)); r = UP5(CC_SEL(cc, 89)); a = UP5(CC_SEL(cc, 114)); } else { b = LERP(3, t, UP5(col0[BCOMP]), UP5(CC_SEL(cc, 79))); g = LERP(3, t, UP5(col0[GCOMP]), UP5(CC_SEL(cc, 84))); r = LERP(3, t, UP5(col0[RCOMP]), UP5(CC_SEL(cc, 89))); a = 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 */ r = g = b = a = 0; } else { GLuint kk; cc = (const GLuint *)code; a = UP5(cc[3] >> (t * 5 + 13)); t *= 15; cc = (const GLuint *)(code + 8 + t / 8); kk = cc[0] >> (t & 7); b = UP5(kk); g = UP5(kk >> 5); r = UP5(kk >> 10); } } rgba[RCOMP] = UBYTE_TO_CHAN(r); rgba[GCOMP] = UBYTE_TO_CHAN(g); rgba[BCOMP] = UBYTE_TO_CHAN(b); rgba[ACOMP] = UBYTE_TO_CHAN(a);}voidfxt1_decode_1 (const void *texture, GLint stride, /* in pixels */ GLint i, GLint j, GLchan *rgba){ static void (*decode_1[]) (const GLubyte *, GLint, GLchan *) = { 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 + -