ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

fxt1.c
Go to the documentation of this file.
00001 /*
00002  * FXT1 codec
00003  * Version:  1.1
00004  *
00005  * Copyright (C) 2004  Daniel Borca   All Rights Reserved.
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a
00008  * copy of this software and associated documentation files (the "Software"),
00009  * to deal in the Software without restriction, including without limitation
00010  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011  * and/or sell copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included
00015  * in all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00020  * DANIEL BORCA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00025 
00026 #include <stdlib.h>
00027 #include <string.h>
00028 
00029 #include "types.h"
00030 #include "internal.h"
00031 #include "fxt1.h"
00032 
00033 
00034 /***************************************************************************\
00035  * FXT1 encoder
00036  *
00037  * The encoder was built by reversing the decoder,
00038  * and is vaguely based on Texus2 by 3dfx. Note that this code
00039  * is merely a proof of concept, since it is highly UNoptimized;
00040  * moreover, it is sub-optimal due to initial conditions passed
00041  * to Lloyd's algorithm (the interpolation modes are even worse).
00042 \***************************************************************************/
00043 
00044 
00045 #define MAX_COMP 4 /* ever needed maximum number of components in texel */
00046 #define MAX_VECT 4 /* ever needed maximum number of base vectors to find */
00047 #define N_TEXELS 32 /* number of texels in a block (always 32) */
00048 #define LL_N_REP 50 /* number of iterations in lloyd's vq */
00049 #define LL_RMS_D 10 /* fault tolerance (maximum delta) */
00050 #define LL_RMS_E 255 /* fault tolerance (maximum error) */
00051 #define ALPHA_TS 2 /* alpha threshold: (255 - ALPHA_TS) deemed opaque */
00052 #define ISTBLACK(v) (*((dword *)(v)) == 0)
00053 #define COPY_4UBV(DST, SRC) *((dword *)(DST)) = *((dword *)(SRC))
00054 
00055 
00056 static int
00057 fxt1_bestcol (float vec[][MAX_COMP], int nv,
00058           byte input[MAX_COMP], int nc)
00059 {
00060     int i, j, best = -1;
00061     float err = 1e9; /* big enough */
00062 
00063     for (j = 0; j < nv; j++) {
00064     float e = 0.0F;
00065     for (i = 0; i < nc; i++) {
00066         e += (vec[j][i] - input[i]) * (vec[j][i] - input[i]);
00067     }
00068     if (e < err) {
00069         err = e;
00070         best = j;
00071     }
00072     }
00073 
00074     return best;
00075 }
00076 
00077 
00078 static int
00079 fxt1_worst (float vec[MAX_COMP],
00080         byte input[N_TEXELS][MAX_COMP], int nc, int n)
00081 {
00082     int i, k, worst = -1;
00083     float err = -1.0F; /* small enough */
00084 
00085     for (k = 0; k < n; k++) {
00086     float e = 0.0F;
00087     for (i = 0; i < nc; i++) {
00088         e += (vec[i] - input[k][i]) * (vec[i] - input[k][i]);
00089     }
00090     if (e > err) {
00091         err = e;
00092         worst = k;
00093     }
00094     }
00095 
00096     return worst;
00097 }
00098 
00099 
00100 static int
00101 fxt1_variance (double variance[MAX_COMP],
00102            byte input[N_TEXELS][MAX_COMP], int nc, int n)
00103 {
00104     int i, k, best = 0;
00105     dword sx, sx2;
00106     double var, maxvar = -1; /* small enough */
00107     double teenth = 1.0 / n;
00108 
00109     for (i = 0; i < nc; i++) {
00110     sx = sx2 = 0;
00111     for (k = 0; k < n; k++) {
00112         int t = input[k][i];
00113         sx += t;
00114         sx2 += t * t;
00115     }
00116     var = sx2 * teenth - sx * sx * teenth * teenth;
00117     if (maxvar < var) {
00118         maxvar = var;
00119         best = i;
00120     }
00121     if (variance) {
00122         variance[i] = var;
00123     }
00124     }
00125 
00126     return best;
00127 }
00128 
00129 
00130 static int
00131 fxt1_choose (float vec[][MAX_COMP], int nv,
00132          byte input[N_TEXELS][MAX_COMP], int nc, int n)
00133 {
00134 #if 0
00135     /* Choose colors from a grid.
00136      */
00137     int i, j;
00138 
00139     for (j = 0; j < nv; j++) {
00140     int m = j * (n - 1) / (nv - 1);
00141     for (i = 0; i < nc; i++) {
00142         vec[j][i] = input[m][i];
00143     }
00144     }
00145 #else
00146     /* Our solution here is to find the darkest and brightest colors in
00147      * the 8x4 tile and use those as the two representative colors.
00148      * There are probably better algorithms to use (histogram-based).
00149      */
00150     int i, j, k;
00151     int minSum = 2000; /* big enough */
00152     int maxSum = -1; /* small enough */
00153     int minCol = 0; /* phoudoin: silent compiler! */
00154     int maxCol = 0; /* phoudoin: silent compiler! */
00155 
00156     struct {
00157     int flag;
00158     dword key;
00159     int freq;
00160     int idx;
00161     } hist[N_TEXELS];
00162     int lenh = 0;
00163 
00164     memset(hist, 0, sizeof(hist));
00165 
00166     for (k = 0; k < n; k++) {
00167     int l;
00168     dword key = 0;
00169     int sum = 0;
00170     for (i = 0; i < nc; i++) {
00171         key <<= 8;
00172         key |= input[k][i];
00173         sum += input[k][i];
00174     }
00175     for (l = 0; l < n; l++) {
00176         if (!hist[l].flag) {
00177         /* alloc new slot */
00178         hist[l].flag = !0;
00179         hist[l].key = key;
00180         hist[l].freq = 1;
00181         hist[l].idx = k;
00182         lenh = l + 1;
00183         break;
00184         } else if (hist[l].key == key) {
00185         hist[l].freq++;
00186         break;
00187         }
00188     }
00189     if (minSum > sum) {
00190         minSum = sum;
00191         minCol = k;
00192     }
00193     if (maxSum < sum) {
00194         maxSum = sum;
00195         maxCol = k;
00196     }
00197     }
00198 
00199     if (lenh <= nv) {
00200     for (j = 0; j < lenh; j++) {
00201         for (i = 0; i < nc; i++) {
00202         vec[j][i] = (float)input[hist[j].idx][i];
00203         }
00204     }
00205     for (; j < nv; j++) {
00206         for (i = 0; i < nc; i++) {
00207         vec[j][i] = vec[0][i];
00208         }
00209     }
00210     return 0;
00211     }
00212 
00213     for (j = 0; j < nv; j++) {
00214     for (i = 0; i < nc; i++) {
00215         vec[j][i] = ((nv - 1 - j) * input[minCol][i] + j * input[maxCol][i] + (nv - 1) / 2) / (float)(nv - 1);
00216     }
00217     }
00218 #endif
00219 
00220     return !0;
00221 }
00222 
00223 
00224 static int
00225 fxt1_lloyd (float vec[][MAX_COMP], int nv,
00226         byte input[N_TEXELS][MAX_COMP], int nc, int n)
00227 {
00228     /* Use the generalized lloyd's algorithm for VQ:
00229      *     find 4 color vectors.
00230      *
00231      *     for each sample color
00232      *         sort to nearest vector.
00233      *
00234      *     replace each vector with the centroid of it's matching colors.
00235      *
00236      *     repeat until RMS doesn't improve.
00237      *
00238      *     if a color vector has no samples, or becomes the same as another
00239      *     vector, replace it with the color which is farthest from a sample.
00240      *
00241      * vec[][MAX_COMP]           initial vectors and resulting colors
00242      * nv                        number of resulting colors required
00243      * input[N_TEXELS][MAX_COMP] input texels
00244      * nc                        number of components in input / vec
00245      * n                         number of input samples
00246      */
00247 
00248     int sum[MAX_VECT][MAX_COMP]; /* used to accumulate closest texels */
00249     int cnt[MAX_VECT]; /* how many times a certain vector was chosen */
00250     float error, lasterror = 1e9;
00251 
00252     int i, j, k, rep;
00253 
00254     /* the quantizer */
00255     for (rep = 0; rep < LL_N_REP; rep++) {
00256     /* reset sums & counters */
00257     for (j = 0; j < nv; j++) {
00258         for (i = 0; i < nc; i++) {
00259         sum[j][i] = 0;
00260         }
00261         cnt[j] = 0;
00262     }
00263     error = 0;
00264 
00265     /* scan whole block */
00266     for (k = 0; k < n; k++) {
00267 #if 1
00268         int best = -1;
00269         float err = 1e9; /* big enough */
00270         /* determine best vector */
00271         for (j = 0; j < nv; j++) {
00272         float e = (vec[j][0] - input[k][0]) * (vec[j][0] - input[k][0]) +
00273               (vec[j][1] - input[k][1]) * (vec[j][1] - input[k][1]) +
00274               (vec[j][2] - input[k][2]) * (vec[j][2] - input[k][2]);
00275         if (nc == 4) {
00276             e += (vec[j][3] - input[k][3]) * (vec[j][3] - input[k][3]);
00277         }
00278         if (e < err) {
00279             err = e;
00280             best = j;
00281         }
00282         }
00283 #else
00284         int best = fxt1_bestcol(vec, nv, input[k], nc, &err);
00285 #endif
00286         /* add in closest color */
00287         for (i = 0; i < nc; i++) {
00288         sum[best][i] += input[k][i];
00289         }
00290         /* mark this vector as used */
00291         cnt[best]++;
00292         /* accumulate error */
00293         error += err;
00294     }
00295 
00296     /* check RMS */
00297     if ((error < LL_RMS_E) ||
00298         ((error < lasterror) && ((lasterror - error) < LL_RMS_D))) {
00299         return !0; /* good match */
00300     }
00301     lasterror = error;
00302 
00303     /* move each vector to the barycenter of its closest colors */
00304     for (j = 0; j < nv; j++) {
00305         if (cnt[j]) {
00306         float div = 1.0F / cnt[j];
00307         for (i = 0; i < nc; i++) {
00308             vec[j][i] = div * sum[j][i];
00309         }
00310         } else {
00311         /* this vec has no samples or is identical with a previous vec */
00312         int worst = fxt1_worst(vec[j], input, nc, n);
00313         for (i = 0; i < nc; i++) {
00314             vec[j][i] = input[worst][i];
00315         }
00316         }
00317     }
00318     }
00319 
00320     return 0; /* could not converge fast enough */
00321 }
00322 
00323 
00324 static void
00325 fxt1_quantize_CHROMA (dword *cc,
00326               byte input[N_TEXELS][MAX_COMP])
00327 {
00328     const int n_vect = 4; /* 4 base vectors to find */
00329     const int n_comp = 3; /* 3 components: R, G, B */
00330     float vec[MAX_VECT][MAX_COMP];
00331     int i, j, k;
00332     qword hi; /* high quadword */
00333     dword lohi, lolo; /* low quadword: hi dword, lo dword */
00334 
00335     if (fxt1_choose(vec, n_vect, input, n_comp, N_TEXELS) != 0) {
00336     fxt1_lloyd(vec, n_vect, input, n_comp, N_TEXELS);
00337     }
00338 
00339     Q_MOV32(hi, 4); /* cc-chroma = "010" + unused bit */
00340     for (j = n_vect - 1; j >= 0; j--) {
00341     for (i = 0; i < n_comp; i++) {
00342         /* add in colors */
00343         Q_SHL(hi, 5);
00344         Q_OR32(hi, (dword)(vec[j][i] / 8.0F));
00345     }
00346     }
00347     ((qword *)cc)[1] = hi;
00348 
00349     lohi = lolo = 0;
00350     /* right microtile */
00351     for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
00352     lohi <<= 2;
00353     lohi |= fxt1_bestcol(vec, n_vect, input[k], n_comp);
00354     }
00355     /* left microtile */
00356     for (; k >= 0; k--) {
00357     lolo <<= 2;
00358     lolo |= fxt1_bestcol(vec, n_vect, input[k], n_comp);
00359     }
00360     cc[1] = lohi;
00361     cc[0] = lolo;
00362 }
00363 
00364 
00365 static void
00366 fxt1_quantize_ALPHA0 (dword *cc,
00367               byte input[N_TEXELS][MAX_COMP],
00368               byte reord[N_TEXELS][MAX_COMP], int n)
00369 {
00370     const int n_vect = 3; /* 3 base vectors to find */
00371     const int n_comp = 4; /* 4 components: R, G, B, A */
00372     float vec[MAX_VECT][MAX_COMP];
00373     int i, j, k;
00374     qword hi; /* high quadword */
00375     dword lohi, lolo; /* low quadword: hi dword, lo dword */
00376 
00377     /* the last vector indicates zero */
00378     for (i = 0; i < n_comp; i++) {
00379     vec[n_vect][i] = 0;
00380     }
00381 
00382     /* the first n texels in reord are guaranteed to be non-zero */
00383     if (fxt1_choose(vec, n_vect, reord, n_comp, n) != 0) {
00384     fxt1_lloyd(vec, n_vect, reord, n_comp, n);
00385     }
00386 
00387     Q_MOV32(hi, 6); /* alpha = "011" + lerp = 0 */
00388     for (j = n_vect - 1; j >= 0; j--) {
00389     /* add in alphas */
00390     Q_SHL(hi, 5);
00391     Q_OR32(hi, (dword)(vec[j][ACOMP] / 8.0F));
00392     }
00393     for (j = n_vect - 1; j >= 0; j--) {
00394     for (i = 0; i < n_comp - 1; i++) {
00395         /* add in colors */
00396         Q_SHL(hi, 5);
00397         Q_OR32(hi, (dword)(vec[j][i] / 8.0F));
00398     }
00399     }
00400     ((qword *)cc)[1] = hi;
00401 
00402     lohi = lolo = 0;
00403     /* right microtile */
00404     for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
00405     lohi <<= 2;
00406     lohi |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp);
00407     }
00408     /* left microtile */
00409     for (; k >= 0; k--) {
00410     lolo <<= 2;
00411     lolo |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp);
00412     }
00413     cc[1] = lohi;
00414     cc[0] = lolo;
00415 }
00416 
00417 
00418 static void
00419 fxt1_quantize_ALPHA1 (dword *cc,
00420               byte input[N_TEXELS][MAX_COMP])
00421 {
00422     const int n_vect = 3; /* highest vector number in each microtile */
00423     const int n_comp = 4; /* 4 components: R, G, B, A */
00424     float vec[1 + 1 + 1][MAX_COMP]; /* 1.5 extrema for each sub-block */
00425     float b, iv[MAX_COMP]; /* interpolation vector */
00426     int i, j, k;
00427     qword hi; /* high quadword */
00428     dword lohi, lolo; /* low quadword: hi dword, lo dword */
00429 
00430     int minSum;
00431     int maxSum;
00432     int minColL = 0, maxColL = 0;
00433     int minColR = 0, maxColR = 0;
00434     int sumL = 0, sumR = 0;
00435 
00436     /* Our solution here is to find the darkest and brightest colors in
00437      * the 4x4 tile and use those as the two representative colors.
00438      * There are probably better algorithms to use (histogram-based).
00439      */
00440     minSum = 2000; /* big enough */
00441     maxSum = -1; /* small enough */
00442     for (k = 0; k < N_TEXELS / 2; k++) {
00443     int sum = 0;
00444     for (i = 0; i < n_comp; i++) {
00445         sum += input[k][i];
00446     }
00447     if (minSum > sum) {
00448         minSum = sum;
00449         minColL = k;
00450     }
00451     if (maxSum < sum) {
00452         maxSum = sum;
00453         maxColL = k;
00454     }
00455     sumL += sum;
00456     }
00457     minSum = 2000; /* big enough */
00458     maxSum = -1; /* small enough */
00459     for (; k < N_TEXELS; k++) {
00460     int sum = 0;
00461     for (i = 0; i < n_comp; i++) {
00462         sum += input[k][i];
00463     }
00464     if (minSum > sum) {
00465         minSum = sum;
00466         minColR = k;
00467     }
00468     if (maxSum < sum) {
00469         maxSum = sum;
00470         maxColR = k;
00471     }
00472     sumR += sum;
00473     }
00474 
00475     /* choose the common vector (yuck!) */
00476     {
00477     int j1, j2;
00478     int v1 = 0, v2 = 0;
00479     float err = 1e9; /* big enough */
00480     float tv[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */
00481     for (i = 0; i < n_comp; i++) {
00482         tv[0][i] = input[minColL][i];
00483         tv[1][i] = input[maxColL][i];
00484         tv[2][i] = input[minColR][i];
00485         tv[3][i] = input[maxColR][i];
00486     }
00487     for (j1 = 0; j1 < 2; j1++) {
00488         for (j2 = 2; j2 < 4; j2++) {
00489         float e = 0.0F;
00490         for (i = 0; i < n_comp; i++) {
00491             e += (tv[j1][i] - tv[j2][i]) * (tv[j1][i] - tv[j2][i]);
00492         }
00493         if (e < err) {
00494             err = e;
00495             v1 = j1;
00496             v2 = j2;
00497         }
00498         }
00499     }
00500     for (i = 0; i < n_comp; i++) {
00501         vec[0][i] = tv[1 - v1][i];
00502         vec[1][i] = (tv[v1][i] * sumL + tv[v2][i] * sumR) / (sumL + sumR);
00503         vec[2][i] = tv[5 - v2][i];
00504     }
00505     }
00506 
00507     /* left microtile */
00508     cc[0] = 0;
00509     if (minColL != maxColL) {
00510     /* compute interpolation vector */
00511     MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
00512 
00513     /* add in texels */
00514     lolo = 0;
00515     for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
00516         int texel;
00517         /* interpolate color */
00518         CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
00519         /* add in texel */
00520         lolo <<= 2;
00521         lolo |= texel;
00522     }
00523 
00524     cc[0] = lolo;
00525     }
00526 
00527     /* right microtile */
00528     cc[1] = 0;
00529     if (minColR != maxColR) {
00530     /* compute interpolation vector */
00531     MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[1]);
00532 
00533     /* add in texels */
00534     lohi = 0;
00535     for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
00536         int texel;
00537         /* interpolate color */
00538         CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
00539         /* add in texel */
00540         lohi <<= 2;
00541         lohi |= texel;
00542     }
00543 
00544     cc[1] = lohi;
00545     }
00546 
00547     Q_MOV32(hi, 7); /* alpha = "011" + lerp = 1 */
00548     for (j = n_vect - 1; j >= 0; j--) {
00549     /* add in alphas */
00550     Q_SHL(hi, 5);
00551     Q_OR32(hi, (dword)(vec[j][ACOMP] / 8.0F));
00552     }
00553     for (j = n_vect - 1; j >= 0; j--) {
00554     for (i = 0; i < n_comp - 1; i++) {
00555         /* add in colors */
00556         Q_SHL(hi, 5);
00557         Q_OR32(hi, (dword)(vec[j][i] / 8.0F));
00558     }
00559     }
00560     ((qword *)cc)[1] = hi;
00561 }
00562 
00563 
00564 static void
00565 fxt1_quantize_HI (dword *cc,
00566           byte input[N_TEXELS][MAX_COMP],
00567           byte reord[N_TEXELS][MAX_COMP], int n)
00568 {
00569     const int n_vect = 6; /* highest vector number */
00570     const int n_comp = 3; /* 3 components: R, G, B */
00571     float b = 0.0F;       /* phoudoin: silent compiler! */
00572     float iv[MAX_COMP];   /* interpolation vector */
00573     int i, k;
00574     dword hihi; /* high quadword: hi dword */
00575 
00576     int minSum = 2000; /* big enough */
00577     int maxSum = -1; /* small enough */
00578     int minCol = 0; /* phoudoin: silent compiler! */
00579     int maxCol = 0; /* phoudoin: silent compiler! */
00580 
00581     /* Our solution here is to find the darkest and brightest colors in
00582      * the 8x4 tile and use those as the two representative colors.
00583      * There are probably better algorithms to use (histogram-based).
00584      */
00585     for (k = 0; k < n; k++) {
00586     int sum = 0;
00587     for (i = 0; i < n_comp; i++) {
00588         sum += reord[k][i];
00589     }
00590     if (minSum > sum) {
00591         minSum = sum;
00592         minCol = k;
00593     }
00594     if (maxSum < sum) {
00595         maxSum = sum;
00596         maxCol = k;
00597     }
00598     }
00599 
00600     hihi = 0; /* cc-hi = "00" */
00601     for (i = 0; i < n_comp; i++) {
00602     /* add in colors */
00603     hihi <<= 5;
00604     hihi |= reord[maxCol][i] >> 3;
00605     }
00606     for (i = 0; i < n_comp; i++) {
00607     /* add in colors */
00608     hihi <<= 5;
00609     hihi |= reord[minCol][i] >> 3;
00610     }
00611     cc[3] = hihi;
00612     cc[0] = cc[1] = cc[2] = 0;
00613 
00614     /* compute interpolation vector */
00615     if (minCol != maxCol) {
00616     MAKEIVEC(n_vect, n_comp, iv, b, reord[minCol], reord[maxCol]);
00617     }
00618 
00619     /* add in texels */
00620     for (k = N_TEXELS - 1; k >= 0; k--) {
00621     int t = k * 3;
00622     dword *kk = (dword *)((byte *)cc + t / 8);
00623     int texel = n_vect + 1; /* transparent black */
00624 
00625     if (!ISTBLACK(input[k])) {
00626         if (minCol != maxCol) {
00627         /* interpolate color */
00628         CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
00629         /* add in texel */
00630         kk[0] |= texel << (t & 7);
00631         }
00632     } else {
00633         /* add in texel */
00634         kk[0] |= texel << (t & 7);
00635     }
00636     }
00637 }
00638 
00639 
00640 static void
00641 fxt1_quantize_MIXED1 (dword *cc,
00642               byte input[N_TEXELS][MAX_COMP])
00643 {
00644     const int n_vect = 2; /* highest vector number in each microtile */
00645     const int n_comp = 3; /* 3 components: R, G, B */
00646     byte vec[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */
00647     float b, iv[MAX_COMP]; /* interpolation vector */
00648     int i, j, k;
00649     qword hi; /* high quadword */
00650     dword lohi, lolo; /* low quadword: hi dword, lo dword */
00651 
00652     int minSum;
00653     int maxSum;
00654     int minColL = 0, maxColL = -1;
00655     int minColR = 0, maxColR = -1;
00656 
00657     /* Our solution here is to find the darkest and brightest colors in
00658      * the 4x4 tile and use those as the two representative colors.
00659      * There are probably better algorithms to use (histogram-based).
00660      */
00661     minSum = 2000; /* big enough */
00662     maxSum = -1; /* small enough */
00663     for (k = 0; k < N_TEXELS / 2; k++) {
00664     if (!ISTBLACK(input[k])) {
00665         int sum = 0;
00666         for (i = 0; i < n_comp; i++) {
00667         sum += input[k][i];
00668         }
00669         if (minSum > sum) {
00670         minSum = sum;
00671         minColL = k;
00672         }
00673         if (maxSum < sum) {
00674         maxSum = sum;
00675         maxColL = k;
00676         }
00677     }
00678     }
00679     minSum = 2000; /* big enough */
00680     maxSum = -1; /* small enough */
00681     for (; k < N_TEXELS; k++) {
00682     if (!ISTBLACK(input[k])) {
00683         int sum = 0;
00684         for (i = 0; i < n_comp; i++) {
00685         sum += input[k][i];
00686         }
00687         if (minSum > sum) {
00688         minSum = sum;
00689         minColR = k;
00690         }
00691         if (maxSum < sum) {
00692         maxSum = sum;
00693         maxColR = k;
00694         }
00695     }
00696     }
00697 
00698     /* left microtile */
00699     if (maxColL == -1) {
00700     /* all transparent black */
00701     cc[0] = ~0UL;
00702     for (i = 0; i < n_comp; i++) {
00703         vec[0][i] = 0;
00704         vec[1][i] = 0;
00705     }
00706     } else {
00707     cc[0] = 0;
00708     for (i = 0; i < n_comp; i++) {
00709         vec[0][i] = input[minColL][i];
00710         vec[1][i] = input[maxColL][i];
00711     }
00712     if (minColL != maxColL) {
00713         /* compute interpolation vector */
00714         MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
00715 
00716         /* add in texels */
00717         lolo = 0;
00718         for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
00719         int texel = n_vect + 1; /* transparent black */
00720         if (!ISTBLACK(input[k])) {
00721             /* interpolate color */
00722             CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
00723         }
00724         /* add in texel */
00725         lolo <<= 2;
00726         lolo |= texel;
00727         }
00728         cc[0] = lolo;
00729     }
00730     }
00731 
00732     /* right microtile */
00733     if (maxColR == -1) {
00734     /* all transparent black */
00735     cc[1] = ~0UL;
00736     for (i = 0; i < n_comp; i++) {
00737         vec[2][i] = 0;
00738         vec[3][i] = 0;
00739     }
00740     } else {
00741     cc[1] = 0;
00742     for (i = 0; i < n_comp; i++) {
00743         vec[2][i] = input[minColR][i];
00744         vec[3][i] = input[maxColR][i];
00745     }
00746     if (minColR != maxColR) {
00747         /* compute interpolation vector */
00748         MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]);
00749 
00750         /* add in texels */
00751         lohi = 0;
00752         for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
00753         int texel = n_vect + 1; /* transparent black */
00754         if (!ISTBLACK(input[k])) {
00755             /* interpolate color */
00756             CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
00757         }
00758         /* add in texel */
00759         lohi <<= 2;
00760         lohi |= texel;
00761         }
00762         cc[1] = lohi;
00763     }
00764     }
00765 
00766     Q_MOV32(hi, 9 | (vec[3][GCOMP] & 4) | ((vec[1][GCOMP] >> 1) & 2)); /* chroma = "1" */
00767     for (j = 2 * 2 - 1; j >= 0; j--) {
00768     for (i = 0; i < n_comp; i++) {
00769         /* add in colors */
00770         Q_SHL(hi, 5);
00771         Q_OR32(hi, vec[j][i] >> 3);
00772     }
00773     }
00774     ((qword *)cc)[1] = hi;
00775 }
00776 
00777 
00778 static void
00779 fxt1_quantize_MIXED0 (dword *cc,
00780               byte input[N_TEXELS][MAX_COMP])
00781 {
00782     const int n_vect = 3; /* highest vector number in each microtile */
00783     const int n_comp = 3; /* 3 components: R, G, B */
00784     byte vec[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */
00785     float b, iv[MAX_COMP]; /* interpolation vector */
00786     int i, j, k;
00787     qword hi; /* high quadword */
00788     dword lohi, lolo; /* low quadword: hi dword, lo dword */
00789 
00790     int minColL = 0, maxColL = 0;
00791     int minColR = 0, maxColR = 0;
00792 #if 0
00793     int minSum;
00794     int maxSum;
00795 
00796     /* Our solution here is to find the darkest and brightest colors in
00797      * the 4x4 tile and use those as the two representative colors.
00798      * There are probably better algorithms to use (histogram-based).
00799      */
00800     minSum = 2000; /* big enough */
00801     maxSum = -1; /* small enough */
00802     for (k = 0; k < N_TEXELS / 2; k++) {
00803     int sum = 0;
00804     for (i = 0; i < n_comp; i++) {
00805         sum += input[k][i];
00806     }
00807     if (minSum > sum) {
00808         minSum = sum;
00809         minColL = k;
00810     }
00811     if (maxSum < sum) {
00812         maxSum = sum;
00813         maxColL = k;
00814     }
00815     }
00816     minSum = 2000; /* big enough */
00817     maxSum = -1; /* small enough */
00818     for (; k < N_TEXELS; k++) {
00819     int sum = 0;
00820     for (i = 0; i < n_comp; i++) {
00821         sum += input[k][i];
00822     }
00823     if (minSum > sum) {
00824         minSum = sum;
00825         minColR = k;
00826     }
00827     if (maxSum < sum) {
00828         maxSum = sum;
00829         maxColR = k;
00830     }
00831     }
00832 #else
00833     int minVal;
00834     int maxVal;
00835     int maxVarL = fxt1_variance(NULL, input, n_comp, N_TEXELS / 2);
00836     int maxVarR = fxt1_variance(NULL, &input[N_TEXELS / 2], n_comp, N_TEXELS / 2);
00837 
00838     /* Scan the channel with max variance for lo & hi
00839      * and use those as the two representative colors.
00840      */
00841     minVal = 2000; /* big enough */
00842     maxVal = -1; /* small enough */
00843     for (k = 0; k < N_TEXELS / 2; k++) {
00844     int t = input[k][maxVarL];
00845     if (minVal > t) {
00846         minVal = t;
00847         minColL = k;
00848     }
00849     if (maxVal < t) {
00850         maxVal = t;
00851         maxColL = k;
00852     }
00853     }
00854     minVal = 2000; /* big enough */
00855     maxVal = -1; /* small enough */
00856     for (; k < N_TEXELS; k++) {
00857     int t = input[k][maxVarR];
00858     if (minVal > t) {
00859         minVal = t;
00860         minColR = k;
00861     }
00862     if (maxVal < t) {
00863         maxVal = t;
00864         maxColR = k;
00865     }
00866     }
00867 #endif
00868 
00869     /* left microtile */
00870     cc[0] = 0;
00871     for (i = 0; i < n_comp; i++) {
00872     vec[0][i] = input[minColL][i];
00873     vec[1][i] = input[maxColL][i];
00874     }
00875     if (minColL != maxColL) {
00876     /* compute interpolation vector */
00877     MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
00878 
00879     /* add in texels */
00880     lolo = 0;
00881     for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
00882         int texel;
00883         /* interpolate color */
00884         CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
00885         /* add in texel */
00886         lolo <<= 2;
00887         lolo |= texel;
00888     }
00889 
00890     /* funky encoding for LSB of green */
00891     if ((int)((lolo >> 1) & 1) != (((vec[1][GCOMP] ^ vec[0][GCOMP]) >> 2) & 1)) {
00892         for (i = 0; i < n_comp; i++) {
00893         vec[1][i] = input[minColL][i];
00894         vec[0][i] = input[maxColL][i];
00895         }
00896         lolo = ~lolo;
00897     }
00898 
00899     cc[0] = lolo;
00900     }
00901 
00902     /* right microtile */
00903     cc[1] = 0;
00904     for (i = 0; i < n_comp; i++) {
00905     vec[2][i] = input[minColR][i];
00906     vec[3][i] = input[maxColR][i];
00907     }
00908     if (minColR != maxColR) {
00909     /* compute interpolation vector */
00910     MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]);
00911 
00912     /* add in texels */
00913     lohi = 0;
00914     for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
00915         int texel;
00916         /* interpolate color */
00917         CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
00918         /* add in texel */
00919         lohi <<= 2;
00920         lohi |= texel;
00921     }
00922 
00923     /* funky encoding for LSB of green */
00924     if ((int)((lohi >> 1) & 1) != (((vec[3][GCOMP] ^ vec[2][GCOMP]) >> 2) & 1)) {
00925         for (i = 0; i < n_comp; i++) {
00926         vec[3][i] = input[minColR][i];
00927         vec[2][i] = input[maxColR][i];
00928         }
00929         lohi = ~lohi;
00930     }
00931 
00932     cc[1] = lohi;
00933     }
00934 
00935     Q_MOV32(hi, 8 | (vec[3][GCOMP] & 4) | ((vec[1][GCOMP] >> 1) & 2)); /* chroma = "1" */
00936     for (j = 2 * 2 - 1; j >= 0; j--) {
00937     for (i = 0; i < n_comp; i++) {
00938         /* add in colors */
00939         Q_SHL(hi, 5);
00940         Q_OR32(hi, vec[j][i] >> 3);
00941     }
00942     }
00943     ((qword *)cc)[1] = hi;
00944 }
00945 
00946 
00947 static void
00948 fxt1_quantize (dword *cc, const byte *lines[], int comps)
00949 {
00950     int trualpha;
00951     byte reord[N_TEXELS][MAX_COMP];
00952 
00953     byte input[N_TEXELS][MAX_COMP];
00954     int i, k, l;
00955 
00956     if (comps == 3) {
00957     /* make the whole block opaque */
00958     memset(input, -1, sizeof(input));
00959     }
00960 
00961     /* 8 texels each line */
00962     for (l = 0; l < 4; l++) {
00963     for (k = 0; k < 4; k++) {
00964         for (i = 0; i < comps; i++) {
00965         input[k + l * 4][i] = *lines[l]++;
00966         }
00967     }
00968     for (; k < 8; k++) {
00969         for (i = 0; i < comps; i++) {
00970         input[k + l * 4 + 12][i] = *lines[l]++;
00971         }
00972     }
00973     }
00974 
00975     /* block layout:
00976      * 00, 01, 02, 03, 08, 09, 0a, 0b
00977      * 10, 11, 12, 13, 18, 19, 1a, 1b
00978      * 04, 05, 06, 07, 0c, 0d, 0e, 0f
00979      * 14, 15, 16, 17, 1c, 1d, 1e, 1f
00980      */
00981 
00982     /* [dBorca]
00983      * stupidity flows forth from this
00984      */
00985     l = N_TEXELS;
00986     trualpha = 0;
00987     if (comps == 4) {
00988     /* skip all transparent black texels */
00989     l = 0;
00990     for (k = 0; k < N_TEXELS; k++) {
00991         /* test all components against 0 */
00992         if (!ISTBLACK(input[k])) {
00993         /* texel is not transparent black */
00994         COPY_4UBV(reord[l], input[k]);
00995         if (reord[l][ACOMP] < (255 - ALPHA_TS)) {
00996             /* non-opaque texel */
00997             trualpha = !0;
00998         }
00999         l++;
01000         }
01001     }
01002     }
01003 
01004 #if 0
01005     if (trualpha) {
01006     fxt1_quantize_ALPHA0(cc, input, reord, l);
01007     } else if (l == 0) {
01008     cc[0] = cc[1] = cc[2] = -1;
01009     cc[3] = 0;
01010     } else if (l < N_TEXELS) {
01011     fxt1_quantize_HI(cc, input, reord, l);
01012     } else {
01013     fxt1_quantize_CHROMA(cc, input);
01014     }
01015     (void)fxt1_quantize_ALPHA1;
01016     (void)fxt1_quantize_MIXED1;
01017     (void)fxt1_quantize_MIXED0;
01018 #else
01019     if (trualpha) {
01020     fxt1_quantize_ALPHA1(cc, input);
01021     } else if (l == 0) {
01022     cc[0] = cc[1] = cc[2] = ~0UL;
01023     cc[3] = 0;
01024     } else if (l < N_TEXELS) {
01025     fxt1_quantize_MIXED1(cc, input);
01026     } else {
01027     fxt1_quantize_MIXED0(cc, input);
01028     }
01029     (void)fxt1_quantize_ALPHA0;
01030     (void)fxt1_quantize_HI;
01031     (void)fxt1_quantize_CHROMA;
01032 #endif
01033 }
01034 
01035 
01036 TAPI int TAPIENTRY
01037 fxt1_encode (int width, int height, int comps,
01038          const void *source, int srcRowStride,
01039          void *dest, int destRowStride)
01040 {
01041     int x, y;
01042     const byte *data;
01043     dword *encoded = (dword *)dest;
01044     void *newSource = NULL;
01045 
01046     /* Replicate image if width is not M8 or height is not M4 */
01047     if ((width & 7) | (height & 3)) {
01048     int newWidth = (width + 7) & ~7;
01049     int newHeight = (height + 3) & ~3;
01050     newSource = malloc(comps * newWidth * newHeight * sizeof(byte *));
01051     _mesa_upscale_teximage2d(width, height, newWidth, newHeight,
01052                  comps, (const byte *)source,
01053                  srcRowStride, (byte *)newSource);
01054     source = newSource;
01055     width = newWidth;
01056     height = newHeight;
01057     srcRowStride = comps * newWidth;
01058     }
01059 
01060     data = (const byte *)source;
01061     destRowStride = (destRowStride - width * 2) / 4;
01062     for (y = 0; y < height; y += 4) {
01063     unsigned int offs = 0 + (y + 0) * srcRowStride;
01064     for (x = 0; x < width; x += 8) {
01065         const byte *lines[4];
01066         lines[0] = &data[offs];
01067         lines[1] = lines[0] + srcRowStride;
01068         lines[2] = lines[1] + srcRowStride;
01069         lines[3] = lines[2] + srcRowStride;
01070         offs += 8 * comps;
01071         fxt1_quantize(encoded, lines, comps);
01072         /* 128 bits per 8x4 block */
01073         encoded += 4;
01074     }
01075     encoded += destRowStride;
01076     }
01077 
01078     if (newSource != NULL) {
01079     free(newSource);
01080     }
01081 
01082     return 0;
01083 }
01084 
01085 
01086 /***************************************************************************\
01087  * FXT1 decoder
01088  *
01089  * The decoder is based on GL_3DFX_texture_compression_FXT1
01090  * specification and serves as a concept for the encoder.
01091 \***************************************************************************/
01092 
01093 
01094 /* lookup table for scaling 5 bit colors up to 8 bits */
01095 static const byte _rgb_scale_5[] = {
01096     0,   8,   16,  25,  33,  41,  49,  58,
01097     66,  74,  82,  90,  99,  107, 115, 123,
01098     132, 140, 148, 156, 165, 173, 181, 189,
01099     197, 206, 214, 222, 230, 239, 247, 255
01100 };
01101 
01102 /* lookup table for scaling 6 bit colors up to 8 bits */
01103 static const byte _rgb_scale_6[] = {
01104     0,   4,   8,   12,  16,  20,  24,  28,
01105     32,  36,  40,  45,  49,  53,  57,  61,
01106     65,  69,  73,  77,  81,  85,  89,  93,
01107     97,  101, 105, 109, 113, 117, 121, 125,
01108     130, 134, 138, 142, 146, 150, 154, 158,
01109     162, 166, 170, 174, 178, 182, 186, 190,
01110     194, 198, 202, 206, 210, 215, 219, 223,
01111     227, 231, 235, 239, 243, 247, 251, 255
01112 };
01113 
01114 
01115 #define CC_SEL(cc, which) (((dword *)(cc))[(which) / 32] >> ((which) & 31))
01116 #define UP5(c) _rgb_scale_5[(c) & 31]
01117 #define UP6(c, b) _rgb_scale_6[(((c) & 31) << 1) | ((b) & 1)]
01118 #define LERP(n, t, c0, c1) (((n) - (t)) * (c0) + (t) * (c1) + (n) / 2) / (n)
01119 #define ZERO_4UBV(v) *((dword *)(v)) = 0
01120 
01121 
01122 static void
01123 fxt1_decode_1HI (const byte *code, int t, byte *rgba)
01124 {
01125     const dword *cc;
01126 
01127     t *= 3;
01128     cc = (const dword *)(code + t / 8);
01129     t = (cc[0] >> (t & 7)) & 7;
01130 
01131     if (t == 7) {
01132     ZERO_4UBV(rgba);
01133     } else {
01134     cc = (const dword *)(code + 12);
01135     if (t == 0) {
01136         rgba[BCOMP] = UP5(CC_SEL(cc, 0));
01137         rgba[GCOMP] = UP5(CC_SEL(cc, 5));
01138         rgba[RCOMP] = UP5(CC_SEL(cc, 10));
01139     } else if (t == 6) {
01140         rgba[BCOMP] = UP5(CC_SEL(cc, 15));
01141         rgba[GCOMP] = UP5(CC_SEL(cc, 20));
01142         rgba[RCOMP] = UP5(CC_SEL(cc, 25));
01143     } else {
01144         rgba[BCOMP] = LERP(6, t, UP5(CC_SEL(cc, 0)), UP5(CC_SEL(cc, 15)));
01145         rgba[GCOMP] = LERP(6, t, UP5(CC_SEL(cc, 5)), UP5(CC_SEL(cc, 20)));
01146         rgba[RCOMP] = LERP(6, t, UP5(CC_SEL(cc, 10)), UP5(CC_SEL(cc, 25)));
01147     }
01148     rgba[ACOMP] = 255;
01149     }
01150 }
01151 
01152 
01153 static void
01154 fxt1_decode_1CHROMA (const byte *code, int t, byte *rgba)
01155 {
01156     const dword *cc;
01157     dword kk;
01158 
01159     cc = (const dword *)code;
01160     if (t & 16) {
01161     cc++;
01162     t &= 15;
01163     }
01164     t = (cc[0] >> (t * 2)) & 3;
01165 
01166     t *= 15;
01167     cc = (const dword *)(code + 8 + t / 8);
01168     kk = cc[0] >> (t & 7);
01169     rgba[BCOMP] = UP5(kk);
01170     rgba[GCOMP] = UP5(kk >> 5);
01171     rgba[RCOMP] = UP5(kk >> 10);
01172     rgba[ACOMP] = 255;
01173 }
01174 
01175 
01176 static void
01177 fxt1_decode_1MIXED (const byte *code, int t, byte *rgba)
01178 {
01179     const dword *cc;
01180     int col[2][3];
01181     int glsb, selb;
01182 
01183     cc = (const dword *)code;
01184     if (t & 16) {
01185     t &= 15;
01186     t = (cc[1] >> (t * 2)) & 3;
01187     /* col 2 */
01188     col[0][BCOMP] = (*(const dword *)(code + 11)) >> 6;
01189     col[0][GCOMP] = CC_SEL(cc, 99);
01190     col[0][RCOMP] = CC_SEL(cc, 104);
01191     /* col 3 */
01192     col[1][BCOMP] = CC_SEL(cc, 109);
01193     col[1][GCOMP] = CC_SEL(cc, 114);
01194     col[1][RCOMP] = CC_SEL(cc, 119);
01195     glsb = CC_SEL(cc, 126);
01196     selb = CC_SEL(cc, 33);
01197     } else {
01198     t = (cc[0] >> (t * 2)) & 3;
01199     /* col 0 */
01200     col[0][BCOMP] = CC_SEL(cc, 64);
01201     col[0][GCOMP] = CC_SEL(cc, 69);
01202     col[0][RCOMP] = CC_SEL(cc, 74);
01203     /* col 1 */
01204     col[1][BCOMP] = CC_SEL(cc, 79);
01205     col[1][GCOMP] = CC_SEL(cc, 84);
01206     col[1][RCOMP] = CC_SEL(cc, 89);
01207     glsb = CC_SEL(cc, 125);
01208     selb = CC_SEL(cc, 1);
01209     }
01210 
01211     if (CC_SEL(cc, 124) & 1) {
01212     /* alpha[0] == 1 */
01213 
01214     if (t == 3) {
01215         ZERO_4UBV(rgba);
01216     } else {
01217         if (t == 0) {
01218         rgba[BCOMP] = UP5(col[0][BCOMP]);
01219         rgba[GCOMP] = UP5(col[0][GCOMP]);
01220         rgba[RCOMP] = UP5(col[0][RCOMP]);
01221         } else if (t == 2) {
01222         rgba[BCOMP] = UP5(col[1][BCOMP]);
01223         rgba[GCOMP] = UP6(col[1][GCOMP], glsb);
01224         rgba[RCOMP] = UP5(col[1][RCOMP]);
01225         } else {
01226         rgba[BCOMP] = (UP5(col[0][BCOMP]) + UP5(col[1][BCOMP])) / 2;
01227         rgba[GCOMP] = (UP5(col[0][GCOMP]) + UP6(col[1][GCOMP], glsb)) / 2;
01228         rgba[RCOMP] = (UP5(col[0][RCOMP]) + UP5(col[1][RCOMP])) / 2;
01229         }
01230         rgba[ACOMP] = 255;
01231     }
01232     } else {
01233     /* alpha[0] == 0 */
01234 
01235     if (t == 0) {
01236         rgba[BCOMP] = UP5(col[0][BCOMP]);
01237         rgba[GCOMP] = UP6(col[0][GCOMP], glsb ^ selb);
01238         rgba[RCOMP] = UP5(col[0][RCOMP]);
01239     } else if (t == 3) {
01240         rgba[BCOMP] = UP5(col[1][BCOMP]);
01241         rgba[GCOMP] = UP6(col[1][GCOMP], glsb);
01242         rgba[RCOMP] = UP5(col[1][RCOMP]);
01243     } else {
01244         rgba[BCOMP] = LERP(3, t, UP5(col[0][BCOMP]), UP5(col[1][BCOMP]));
01245         rgba[GCOMP] = LERP(3, t, UP6(col[0][GCOMP], glsb ^ selb),
01246                      UP6(col[1][GCOMP], glsb));
01247         rgba[RCOMP] = LERP(3, t, UP5(col[0][RCOMP]), UP5(col[1][RCOMP]));
01248     }
01249     rgba[ACOMP] = 255;
01250     }
01251 }
01252 
01253 
01254 static void
01255 fxt1_decode_1ALPHA (const byte *code, int t, byte *rgba)
01256 {
01257     const dword *cc;
01258 
01259     cc = (const dword *)code;
01260     if (CC_SEL(cc, 124) & 1) {
01261     /* lerp == 1 */
01262     int col0[4];
01263 
01264     if (t & 16) {
01265         t &= 15;
01266         t = (cc[1] >> (t * 2)) & 3;
01267         /* col 2 */
01268         col0[BCOMP] = (*(const dword *)(code + 11)) >> 6;
01269         col0[GCOMP] = CC_SEL(cc, 99);
01270         col0[RCOMP] = CC_SEL(cc, 104);
01271         col0[ACOMP] = CC_SEL(cc, 119);
01272     } else {
01273         t = (cc[0] >> (t * 2)) & 3;
01274         /* col 0 */
01275         col0[BCOMP] = CC_SEL(cc, 64);
01276         col0[GCOMP] = CC_SEL(cc, 69);
01277         col0[RCOMP] = CC_SEL(cc, 74);
01278         col0[ACOMP] = CC_SEL(cc, 109);
01279     }
01280 
01281     if (t == 0) {
01282         rgba[BCOMP] = UP5(col0[BCOMP]);
01283         rgba[GCOMP] = UP5(col0[GCOMP]);
01284         rgba[RCOMP] = UP5(col0[RCOMP]);
01285         rgba[ACOMP] = UP5(col0[ACOMP]);
01286     } else if (t == 3) {
01287         rgba[BCOMP] = UP5(CC_SEL(cc, 79));
01288         rgba[GCOMP] = UP5(CC_SEL(cc, 84));
01289         rgba[RCOMP] = UP5(CC_SEL(cc, 89));
01290         rgba[ACOMP] = UP5(CC_SEL(cc, 114));
01291     } else {
01292         rgba[BCOMP] = LERP(3, t, UP5(col0[BCOMP]), UP5(CC_SEL(cc, 79)));
01293         rgba[GCOMP] = LERP(3, t, UP5(col0[GCOMP]), UP5(CC_SEL(cc, 84)));
01294         rgba[RCOMP] = LERP(3, t, UP5(col0[RCOMP]), UP5(CC_SEL(cc, 89)));
01295         rgba[ACOMP] = LERP(3, t, UP5(col0[ACOMP]), UP5(CC_SEL(cc, 114)));
01296     }
01297     } else {
01298     /* lerp == 0 */
01299 
01300     if (t & 16) {
01301         cc++;
01302         t &= 15;
01303     }
01304     t = (cc[0] >> (t * 2)) & 3;
01305 
01306     if (t == 3) {
01307         ZERO_4UBV(rgba);
01308     } else {
01309         dword kk;
01310         cc = (const dword *)code;
01311         rgba[ACOMP] = UP5(cc[3] >> (t * 5 + 13));
01312         t *= 15;
01313         cc = (const dword *)(code + 8 + t / 8);
01314         kk = cc[0] >> (t & 7);
01315         rgba[BCOMP] = UP5(kk);
01316         rgba[GCOMP] = UP5(kk >> 5);
01317         rgba[RCOMP] = UP5(kk >> 10);
01318     }
01319     }
01320 }
01321 
01322 
01323 TAPI void TAPIENTRY
01324 fxt1_decode_1 (const void *texture, int stride,
01325            int i, int j, byte *rgba)
01326 {
01327     static void (*decode_1[]) (const byte *, int, byte *) = {
01328     fxt1_decode_1HI,    /* cc-high   = "00?" */
01329     fxt1_decode_1HI,    /* cc-high   = "00?" */
01330     fxt1_decode_1CHROMA,    /* cc-chroma = "010" */
01331     fxt1_decode_1ALPHA, /* alpha     = "011" */
01332     fxt1_decode_1MIXED, /* mixed     = "1??" */
01333     fxt1_decode_1MIXED, /* mixed     = "1??" */
01334     fxt1_decode_1MIXED, /* mixed     = "1??" */
01335     fxt1_decode_1MIXED  /* mixed     = "1??" */
01336     };
01337 
01338     const byte *code = (const byte *)texture +
01339             ((j / 4) * (stride / 8) + (i / 8)) * 16;
01340     int mode = CC_SEL(code, 125);
01341     int t = i & 7;
01342 
01343     if (t & 4) {
01344     t += 12;
01345     }
01346     t += (j & 3) * 4;
01347 
01348     decode_1[mode](code, t, rgba);
01349 
01350 #if VERBOSE
01351     {
01352     extern int cc_chroma;
01353     extern int cc_alpha;
01354     extern int cc_high;
01355     extern int cc_mixed;
01356     static int *cctype[] = {
01357         &cc_high,
01358         &cc_high,
01359         &cc_chroma,
01360         &cc_alpha,
01361         &cc_mixed,
01362         &cc_mixed,
01363         &cc_mixed,
01364         &cc_mixed
01365     };
01366     (*cctype[mode])++;
01367     }
01368 #endif
01369 }

Generated on Sun May 27 2012 04:19:21 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.