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
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)
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)
*
* 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).
\***************************************************************************/
#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)
* 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! */
}
}
#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++) {
/* 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];
}
* 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;
}
sumL += sum;
}
- minSum = 1000; /* big enough */
+ minSum = 2000; /* big enough */
maxSum = -1; /* small enough */
for (; k < N_TEXELS; k++) {
int sum = 0;
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;
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;
{
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.
/* 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 */
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);
}
* 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])) {
}
}
}
- minSum = 1000; /* big enough */
+ minSum = 2000; /* big enough */
maxSum = -1; /* small enough */
for (; k < N_TEXELS; k++) {
if (!ISTBLACK(input[k])) {
}
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;
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;
}
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;
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;
* 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;
maxColL = k;
}
}
- minSum = 1000; /* big enough */
+ minSum = 2000; /* big enough */
maxSum = -1; /* small enough */
for (; k < N_TEXELS; k++) {
int sum = 0;
/* 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];
maxColL = k;
}
}
- minVal = 1000; /* big enough */
+ minVal = 2000; /* big enough */
maxVal = -1; /* small enough */
for (; k < N_TEXELS; k++) {
int t = input[k][maxVarR];
}
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;
}
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;
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++) {
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;
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;
};
-#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)