cleaned up the mess a bit

This commit is contained in:
Daniel Borca 2004-11-01 09:06:17 +00:00
parent 95e2a8099b
commit 3d2b4bfa95

View file

@ -41,9 +41,7 @@
int
fxt1_encode (GLcontext *ctx,
unsigned int width, unsigned int height,
int srcFormat,
fxt1_encode (unsigned int width, unsigned int height, int comps,
const void *source, int srcRowStride,
void *dest, int destRowStride);
void
@ -107,7 +105,7 @@ texstore_rgb_fxt1(STORE_PARAMS)
GL_COMPRESSED_RGB_FXT1_3DFX,
texWidth, (GLubyte *) dstAddr);
fxt1_encode(ctx, srcWidth, srcHeight, srcFormat, pixels, srcRowStride,
fxt1_encode(srcWidth, srcHeight, 3, pixels, srcRowStride,
dst, dstRowStride);
if (tempImage)
@ -163,7 +161,7 @@ texstore_rgba_fxt1(STORE_PARAMS)
GL_COMPRESSED_RGBA_FXT1_3DFX,
texWidth, (GLubyte *) dstAddr);
fxt1_encode(ctx, srcWidth, srcHeight, srcFormat, pixels, srcRowStride,
fxt1_encode(srcWidth, srcHeight, 4, pixels, srcRowStride,
dst, dstRowStride);
if (tempImage)
@ -273,9 +271,9 @@ const struct gl_texture_format _mesa_texformat_rgba_fxt1 = {
*
* The encoder was built by reversing the decoder,
* and is vaguely based on Texus2 by 3dfx. Note that this code
* is merely a proof of concept, since it is higly UNoptimized;
* moreover, it is sub-optimal due to inital conditions passed
* to Lloyd's algorithm (the interpolation modes are worse).
* is merely a proof of concept, since it is highly UNoptimized;
* moreover, it is sub-optimal due to initial conditions passed
* to Lloyd's algorithm (the interpolation modes are even worse).
\***************************************************************************/
@ -324,6 +322,46 @@ typedef struct {
#endif /* !__GNUC__ */
#define F(i) 1 /* can be used to obtain an oblong metric: 0.30 / 0.59 / 0.11 */
#define SAFECDOT 1 /* for paranoids */
#define MAKEIVEC(NV, NC, IV, B, V0, V1) \
do { \
/* compute interpolation vector */ \
float d2 = 0; \
float rd2; \
\
for (i = 0; i < NC; i++) { \
IV[i] = (V1[i] - V0[i]) * F(i); \
d2 += IV[i] * IV[i]; \
} \
rd2 = (float)NV / d2; \
B = 0; \
for (i = 0; i < NC; i++) { \
IV[i] *= F(i); \
B -= IV[i] * V0[i]; \
IV[i] *= rd2; \
} \
B = B * rd2 + 0.5f; \
} while (0)
#define CALCCDOT(TEXEL, NV, NC, IV, B, V)\
do { \
float dot = 0; \
for (i = 0; i < NC; i++) { \
dot += V[i] * IV[i]; \
} \
TEXEL = (int)(dot + B); \
if (SAFECDOT) { \
if (TEXEL < 0) { \
TEXEL = 0; \
} else if (TEXEL > NV) { \
TEXEL = NV; \
} \
} \
} while (0)
static int
fxt1_bestcol (float vec[][MAX_COMP], int nv,
unsigned char input[MAX_COMP], int nc)
@ -419,7 +457,7 @@ fxt1_choose (float vec[][MAX_COMP], int nv,
* There are probably better algorithms to use (histogram-based).
*/
int i, j, k;
int minSum = 1000; /* big enough */
int minSum = 2000; /* big enough */
int maxSum = -1; /* small enough */
int minCol = 0; /* phoudoin: silent compiler! */
int maxCol = 0; /* phoudoin: silent compiler! */
@ -552,7 +590,7 @@ fxt1_lloyd (float vec[][MAX_COMP], int nv,
}
}
#else
int best = fxt1_bestcol(vec, n_vect, input[k], n_comp, &err);
int best = fxt1_bestcol(vec, nv, input[k], nc, &err);
#endif
/* add in closest color */
for (i = 0; i < nc; i++) {
@ -574,7 +612,7 @@ fxt1_lloyd (float vec[][MAX_COMP], int nv,
/* move each vector to the barycenter of its closest colors */
for (j = 0; j < nv; j++) {
if (cnt[j]) {
float div = 1.0 / cnt[j];
float div = 1.0F / cnt[j];
for (i = 0; i < nc; i++) {
vec[j][i] = div * sum[j][i];
}
@ -708,7 +746,7 @@ fxt1_quantize_ALPHA1 (unsigned long *cc,
* the 4x4 tile and use those as the two representative colors.
* There are probably better algorithms to use (histogram-based).
*/
minSum = 1000; /* big enough */
minSum = 2000; /* big enough */
maxSum = -1; /* small enough */
for (k = 0; k < N_TEXELS / 2; k++) {
int sum = 0;
@ -725,7 +763,7 @@ fxt1_quantize_ALPHA1 (unsigned long *cc,
}
sumL += sum;
}
minSum = 1000; /* big enough */
minSum = 2000; /* big enough */
maxSum = -1; /* small enough */
for (; k < N_TEXELS; k++) {
int sum = 0;
@ -779,36 +817,14 @@ fxt1_quantize_ALPHA1 (unsigned long *cc,
cc[0] = 0;
if (minColL != maxColL) {
/* compute interpolation vector */
float d2 = 0;
float rd2;
for (i = 0; i < n_comp; i++) {
iv[i] = vec[1][i] - vec[0][i];
d2 += iv[i] * iv[i];
}
rd2 = (float)n_vect / d2;
b = 0;
for (i = 0; i < n_comp; i++) {
b -= iv[i] * vec[0][i];
iv[i] *= rd2;
}
b = b * rd2 + 0.5f;
MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
/* add in texels */
lolo = 0;
for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
int texel;
/* interpolate color */
float dot = 0;
for (i = 0; i < n_comp; i++) {
dot += input[k][i] * iv[i];
}
texel = (int)(dot + b);
if (texel < 0) {
texel = 0;
} else if (texel > n_vect) {
texel = n_vect;
}
CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
/* add in texel */
lolo <<= 2;
lolo |= texel;
@ -821,36 +837,14 @@ fxt1_quantize_ALPHA1 (unsigned long *cc,
cc[1] = 0;
if (minColR != maxColR) {
/* compute interpolation vector */
float d2 = 0;
float rd2;
for (i = 0; i < n_comp; i++) {
iv[i] = vec[1][i] - vec[2][i];
d2 += iv[i] * iv[i];
}
rd2 = (float)n_vect / d2;
b = 0;
for (i = 0; i < n_comp; i++) {
b -= iv[i] * vec[2][i];
iv[i] *= rd2;
}
b = b * rd2 + 0.5f;
MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[1]);
/* add in texels */
lohi = 0;
for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
int texel;
/* interpolate color */
float dot = 0;
for (i = 0; i < n_comp; i++) {
dot += input[k][i] * iv[i];
}
texel = (int)(dot + b);
if (texel < 0) {
texel = 0;
} else if (texel > n_vect) {
texel = n_vect;
}
CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
/* add in texel */
lohi <<= 2;
lohi |= texel;
@ -883,15 +877,15 @@ fxt1_quantize_HI (unsigned long *cc,
{
const int n_vect = 6; /* highest vector number */
const int n_comp = 3; /* 3 components: R, G, B */
float b = 0.0; /* phoudoin: silent compiler! */
float iv[MAX_COMP]; /* interpolation vector */
float b = 0.0; /* phoudoin: silent compiler! */
float iv[MAX_COMP]; /* interpolation vector */
int i, k;
unsigned long hihi; /* high quadword: hi dword */
int minSum = 1000; /* big enough */
int minSum = 2000; /* big enough */
int maxSum = -1; /* small enough */
int minCol = 0; /* phoudoin: silent compiler! */
int maxCol = 0; /* phoudoin: silent compiler! */
int minCol = 0; /* phoudoin: silent compiler! */
int maxCol = 0; /* phoudoin: silent compiler! */
/* Our solution here is to find the darkest and brightest colors in
* the 8x4 tile and use those as the two representative colors.
@ -928,20 +922,7 @@ fxt1_quantize_HI (unsigned long *cc,
/* compute interpolation vector */
if (minCol != maxCol) {
float d2 = 0;
float rd2;
for (i = 0; i < n_comp; i++) {
iv[i] = reord[maxCol][i] - reord[minCol][i];
d2 += iv[i] * iv[i];
}
rd2 = (float)n_vect / d2;
b = 0;
for (i = 0; i < n_comp; i++) {
b -= iv[i] * reord[minCol][i];
iv[i] *= rd2;
}
b = b * rd2 + 0.5f;
MAKEIVEC(n_vect, n_comp, iv, b, reord[minCol], reord[maxCol]);
}
/* add in texels */
@ -953,16 +934,7 @@ fxt1_quantize_HI (unsigned long *cc,
if (!ISTBLACK(input[k])) {
if (minCol != maxCol) {
/* interpolate color */
float dot = 0;
for (i = 0; i < n_comp; i++) {
dot += input[k][i] * iv[i];
}
texel = (int)(dot + b);
if (texel < 0) {
texel = 0;
} else if (texel > n_vect) {
texel = n_vect;
}
CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
/* add in texel */
kk[0] |= texel << (t & 7);
}
@ -995,7 +967,7 @@ fxt1_quantize_MIXED1 (unsigned long *cc,
* the 4x4 tile and use those as the two representative colors.
* There are probably better algorithms to use (histogram-based).
*/
minSum = 1000; /* big enough */
minSum = 2000; /* big enough */
maxSum = -1; /* small enough */
for (k = 0; k < N_TEXELS / 2; k++) {
if (!ISTBLACK(input[k])) {
@ -1013,7 +985,7 @@ fxt1_quantize_MIXED1 (unsigned long *cc,
}
}
}
minSum = 1000; /* big enough */
minSum = 2000; /* big enough */
maxSum = -1; /* small enough */
for (; k < N_TEXELS; k++) {
if (!ISTBLACK(input[k])) {
@ -1048,20 +1020,7 @@ fxt1_quantize_MIXED1 (unsigned long *cc,
}
if (minColL != maxColL) {
/* compute interpolation vector */
float d2 = 0;
float rd2;
for (i = 0; i < n_comp; i++) {
iv[i] = vec[1][i] - vec[0][i];
d2 += iv[i] * iv[i];
}
rd2 = (float)n_vect / d2;
b = 0;
for (i = 0; i < n_comp; i++) {
b -= iv[i] * vec[0][i];
iv[i] *= rd2;
}
b = b * rd2 + 0.5f;
MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
/* add in texels */
lolo = 0;
@ -1069,16 +1028,7 @@ fxt1_quantize_MIXED1 (unsigned long *cc,
int texel = n_vect + 1; /* transparent black */
if (!ISTBLACK(input[k])) {
/* interpolate color */
float dot = 0;
for (i = 0; i < n_comp; i++) {
dot += input[k][i] * iv[i];
}
texel = (int)(dot + b);
if (texel < 0) {
texel = 0;
} else if (texel > n_vect) {
texel = n_vect;
}
CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
}
/* add in texel */
lolo <<= 2;
@ -1104,20 +1054,7 @@ fxt1_quantize_MIXED1 (unsigned long *cc,
}
if (minColR != maxColR) {
/* compute interpolation vector */
float d2 = 0;
float rd2;
for (i = 0; i < n_comp; i++) {
iv[i] = vec[3][i] - vec[2][i];
d2 += iv[i] * iv[i];
}
rd2 = (float)n_vect / d2;
b = 0;
for (i = 0; i < n_comp; i++) {
b -= iv[i] * vec[2][i];
iv[i] *= rd2;
}
b = b * rd2 + 0.5f;
MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]);
/* add in texels */
lohi = 0;
@ -1125,16 +1062,7 @@ fxt1_quantize_MIXED1 (unsigned long *cc,
int texel = n_vect + 1; /* transparent black */
if (!ISTBLACK(input[k])) {
/* interpolate color */
float dot = 0;
for (i = 0; i < n_comp; i++) {
dot += input[k][i] * iv[i];
}
texel = (int)(dot + b);
if (texel < 0) {
texel = 0;
} else if (texel > n_vect) {
texel = n_vect;
}
CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
}
/* add in texel */
lohi <<= 2;
@ -1178,7 +1106,7 @@ fxt1_quantize_MIXED0 (unsigned long *cc,
* the 4x4 tile and use those as the two representative colors.
* There are probably better algorithms to use (histogram-based).
*/
minSum = 1000; /* big enough */
minSum = 2000; /* big enough */
maxSum = -1; /* small enough */
for (k = 0; k < N_TEXELS / 2; k++) {
int sum = 0;
@ -1194,7 +1122,7 @@ fxt1_quantize_MIXED0 (unsigned long *cc,
maxColL = k;
}
}
minSum = 1000; /* big enough */
minSum = 2000; /* big enough */
maxSum = -1; /* small enough */
for (; k < N_TEXELS; k++) {
int sum = 0;
@ -1219,7 +1147,7 @@ fxt1_quantize_MIXED0 (unsigned long *cc,
/* Scan the channel with max variance for lo & hi
* and use those as the two representative colors.
*/
minVal = 1000; /* big enough */
minVal = 2000; /* big enough */
maxVal = -1; /* small enough */
for (k = 0; k < N_TEXELS / 2; k++) {
int t = input[k][maxVarL];
@ -1232,7 +1160,7 @@ fxt1_quantize_MIXED0 (unsigned long *cc,
maxColL = k;
}
}
minVal = 1000; /* big enough */
minVal = 2000; /* big enough */
maxVal = -1; /* small enough */
for (; k < N_TEXELS; k++) {
int t = input[k][maxVarR];
@ -1255,36 +1183,14 @@ fxt1_quantize_MIXED0 (unsigned long *cc,
}
if (minColL != maxColL) {
/* compute interpolation vector */
float d2 = 0;
float rd2;
for (i = 0; i < n_comp; i++) {
iv[i] = vec[1][i] - vec[0][i];
d2 += iv[i] * iv[i];
}
rd2 = (float)n_vect / d2;
b = 0;
for (i = 0; i < n_comp; i++) {
b -= iv[i] * vec[0][i];
iv[i] *= rd2;
}
b = b * rd2 + 0.5f;
MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
/* add in texels */
lolo = 0;
for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
int texel;
/* interpolate color */
float dot = 0;
for (i = 0; i < n_comp; i++) {
dot += input[k][i] * iv[i];
}
texel = (int)(dot + b);
if (texel < 0) {
texel = 0;
} else if (texel > n_vect) {
texel = n_vect;
}
CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
/* add in texel */
lolo <<= 2;
lolo |= texel;
@ -1310,36 +1216,14 @@ fxt1_quantize_MIXED0 (unsigned long *cc,
}
if (minColR != maxColR) {
/* compute interpolation vector */
float d2 = 0;
float rd2;
for (i = 0; i < n_comp; i++) {
iv[i] = vec[3][i] - vec[2][i];
d2 += iv[i] * iv[i];
}
rd2 = (float)n_vect / d2;
b = 0;
for (i = 0; i < n_comp; i++) {
b -= iv[i] * vec[2][i];
iv[i] *= rd2;
}
b = b * rd2 + 0.5f;
MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]);
/* add in texels */
lohi = 0;
for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
int texel;
/* interpolate color */
float dot = 0;
for (i = 0; i < n_comp; i++) {
dot += input[k][i] * iv[i];
}
texel = (int)(dot + b);
if (texel < 0) {
texel = 0;
} else if (texel > n_vect) {
texel = n_vect;
}
CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
/* add in texel */
lohi <<= 2;
lohi |= texel;
@ -1378,7 +1262,10 @@ fxt1_quantize (unsigned long *cc, const unsigned char *lines[], int comps)
unsigned char input[N_TEXELS][MAX_COMP];
int i, k, l;
memset(input, -1, sizeof(input));
if (comps == 3) {
/* make the whole block opaque */
memset(input, -1, sizeof(input));
}
/* 8 texels each line */
for (l = 0; l < 4; l++) {
@ -1456,29 +1343,22 @@ fxt1_quantize (unsigned long *cc, const unsigned char *lines[], int comps)
int
fxt1_encode (GLcontext *ctx,
unsigned int width, unsigned int height,
int srcFormat,
fxt1_encode (unsigned int width, unsigned int height, int comps,
const void *source, int srcRowStride,
void *dest, int destRowStride)
{
const int comps = (srcFormat == GL_RGB) ? 3 : 4;
unsigned int x, y;
const unsigned char *data;
unsigned long *encoded = dest;
GLubyte *newSource = NULL;
unsigned char *newSource = NULL;
(void) ctx;
/*
* Rescale image if width is less than 8 or height is less than 4.
*/
if (width < 8 || height < 4) {
GLint newWidth = (width + 7) & ~7;
GLint newHeight = (height + 3) & ~3;
newSource = MALLOC(comps * newWidth * newHeight * sizeof(GLchan));
/* Replicate image if width is not M8 or height is not M4 */
if ((width & 7) | (height & 3)) {
int newWidth = (width + 7) & ~7;
int newHeight = (height + 3) & ~3;
newSource = malloc(comps * newWidth * newHeight * sizeof(unsigned char *));
_mesa_upscale_teximage2d(width, height, newWidth, newHeight,
comps, source, srcRowStride, newSource);
comps, source, srcRowStride, newSource);
source = newSource;
width = newWidth;
height = newHeight;
@ -1497,14 +1377,14 @@ fxt1_encode (GLcontext *ctx,
lines[3] = lines[2] + srcRowStride;
offs += 8 * comps;
fxt1_quantize(encoded, lines, comps);
/* 128 bits per 8x4 block = 4bpp */
/* 128 bits per 8x4 block */
encoded += 4;
}
encoded += destRowStride;
}
if (newSource != NULL) {
FREE(newSource);
free(newSource);
}
return 0;
@ -1540,7 +1420,7 @@ static unsigned char _rgb_scale_6[] = {
};
#define CC_SEL(cc, which) ((cc)[(which) / 32] >> ((which) & 31))
#define CC_SEL(cc, which) (((unsigned long *)(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)