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

texcompress_fxt1.c
Go to the documentation of this file.
00001 /*
00002  * Mesa 3-D graphics library
00003  * Version:  7.1
00004  *
00005  * Copyright (C) 1999-2008  Brian Paul   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  * BRIAN PAUL 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 
00032 #include "glheader.h"
00033 #include "imports.h"
00034 #include "colormac.h"
00035 #include "context.h"
00036 #include "convolve.h"
00037 #include "image.h"
00038 #include "mipmap.h"
00039 #include "texcompress.h"
00040 #include "texformat.h"
00041 #include "texstore.h"
00042 
00043 
00044 static void
00045 fxt1_encode (GLuint width, GLuint height, GLint comps,
00046              const void *source, GLint srcRowStride,
00047              void *dest, GLint destRowStride);
00048 
00049 void
00050 fxt1_decode_1 (const void *texture, GLint stride,
00051                GLint i, GLint j, GLchan *rgba);
00052 
00053 
00057 void
00058 _mesa_init_texture_fxt1( GLcontext *ctx )
00059 {
00060    (void) ctx;
00061 }
00062 
00063 
00067 static GLboolean
00068 texstore_rgb_fxt1(TEXSTORE_PARAMS)
00069 {
00070    const GLchan *pixels;
00071    GLint srcRowStride;
00072    GLubyte *dst;
00073    const GLint texWidth = dstRowStride * 8 / 16; /* a bit of a hack */
00074    const GLchan *tempImage = NULL;
00075 
00076    ASSERT(dstFormat == &_mesa_texformat_rgb_fxt1);
00077    ASSERT(dstXoffset % 8 == 0);
00078    ASSERT(dstYoffset % 4 == 0);
00079    ASSERT(dstZoffset     == 0);
00080    (void) dstZoffset;
00081    (void) dstImageOffsets;
00082 
00083    if (srcFormat != GL_RGB ||
00084        srcType != CHAN_TYPE ||
00085        ctx->_ImageTransferState ||
00086        srcPacking->SwapBytes) {
00087       /* convert image to RGB/GLchan */
00088       tempImage = _mesa_make_temp_chan_image(ctx, dims,
00089                                              baseInternalFormat,
00090                                              dstFormat->BaseFormat,
00091                                              srcWidth, srcHeight, srcDepth,
00092                                              srcFormat, srcType, srcAddr,
00093                                              srcPacking);
00094       if (!tempImage)
00095          return GL_FALSE; /* out of memory */
00096       _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
00097       pixels = tempImage;
00098       srcRowStride = 3 * srcWidth;
00099       srcFormat = GL_RGB;
00100    }
00101    else {
00102       pixels = (const GLchan *) srcAddr;
00103       srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat,
00104                                             srcType) / sizeof(GLchan);
00105    }
00106 
00107    dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
00108                                         dstFormat->MesaFormat,
00109                                         texWidth, (GLubyte *) dstAddr);
00110 
00111    fxt1_encode(srcWidth, srcHeight, 3, pixels, srcRowStride,
00112                dst, dstRowStride);
00113 
00114    if (tempImage)
00115       _mesa_free((void*) tempImage);
00116 
00117    return GL_TRUE;
00118 }
00119 
00120 
00124 static GLboolean
00125 texstore_rgba_fxt1(TEXSTORE_PARAMS)
00126 {
00127    const GLchan *pixels;
00128    GLint srcRowStride;
00129    GLubyte *dst;
00130    GLint texWidth = dstRowStride * 8 / 16; /* a bit of a hack */
00131    const GLchan *tempImage = NULL;
00132 
00133    ASSERT(dstFormat == &_mesa_texformat_rgba_fxt1);
00134    ASSERT(dstXoffset % 8 == 0);
00135    ASSERT(dstYoffset % 4 == 0);
00136    ASSERT(dstZoffset     == 0);
00137    (void) dstZoffset;
00138    (void) dstImageOffsets;
00139 
00140    if (srcFormat != GL_RGBA ||
00141        srcType != CHAN_TYPE ||
00142        ctx->_ImageTransferState ||
00143        srcPacking->SwapBytes) {
00144       /* convert image to RGBA/GLchan */
00145       tempImage = _mesa_make_temp_chan_image(ctx, dims,
00146                                              baseInternalFormat,
00147                                              dstFormat->BaseFormat,
00148                                              srcWidth, srcHeight, srcDepth,
00149                                              srcFormat, srcType, srcAddr,
00150                                              srcPacking);
00151       if (!tempImage)
00152          return GL_FALSE; /* out of memory */
00153       _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
00154       pixels = tempImage;
00155       srcRowStride = 4 * srcWidth;
00156       srcFormat = GL_RGBA;
00157    }
00158    else {
00159       pixels = (const GLchan *) srcAddr;
00160       srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat,
00161                                             srcType) / sizeof(GLchan);
00162    }
00163 
00164    dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0,
00165                                         dstFormat->MesaFormat,
00166                                         texWidth, (GLubyte *) dstAddr);
00167 
00168    fxt1_encode(srcWidth, srcHeight, 4, pixels, srcRowStride,
00169                dst, dstRowStride);
00170 
00171    if (tempImage)
00172       _mesa_free((void*) tempImage);
00173 
00174    return GL_TRUE;
00175 }
00176 
00177 
00178 static void
00179 fetch_texel_2d_rgba_fxt1( const struct gl_texture_image *texImage,
00180                           GLint i, GLint j, GLint k, GLchan *texel )
00181 {
00182    (void) k;
00183    fxt1_decode_1(texImage->Data, texImage->RowStride, i, j, texel);
00184 }
00185 
00186 
00187 static void
00188 fetch_texel_2d_f_rgba_fxt1( const struct gl_texture_image *texImage,
00189                             GLint i, GLint j, GLint k, GLfloat *texel )
00190 {
00191    /* just sample as GLchan and convert to float here */
00192    GLchan rgba[4];
00193    (void) k;
00194    fxt1_decode_1(texImage->Data, texImage->RowStride, i, j, rgba);
00195    texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]);
00196    texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]);
00197    texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]);
00198    texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);
00199 }
00200 
00201 
00202 static void
00203 fetch_texel_2d_rgb_fxt1( const struct gl_texture_image *texImage,
00204                          GLint i, GLint j, GLint k, GLchan *texel )
00205 {
00206    (void) k;
00207    fxt1_decode_1(texImage->Data, texImage->RowStride, i, j, texel);
00208    texel[ACOMP] = 255;
00209 }
00210 
00211 
00212 static void
00213 fetch_texel_2d_f_rgb_fxt1( const struct gl_texture_image *texImage,
00214                            GLint i, GLint j, GLint k, GLfloat *texel )
00215 {
00216    /* just sample as GLchan and convert to float here */
00217    GLchan rgba[4];
00218    (void) k;
00219    fxt1_decode_1(texImage->Data, texImage->RowStride, i, j, rgba);
00220    texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]);
00221    texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]);
00222    texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]);
00223    texel[ACOMP] = 1.0F;
00224 }
00225 
00226 
00227 
00228 const struct gl_texture_format _mesa_texformat_rgb_fxt1 = {
00229    MESA_FORMAT_RGB_FXT1,        /* MesaFormat */
00230    GL_RGB,              /* BaseFormat */
00231    GL_UNSIGNED_NORMALIZED_ARB,      /* DataType */
00232    4, /*approx*/            /* RedBits */
00233    4, /*approx*/            /* GreenBits */
00234    4, /*approx*/            /* BlueBits */
00235    0,                   /* AlphaBits */
00236    0,                   /* LuminanceBits */
00237    0,                   /* IntensityBits */
00238    0,                   /* IndexBits */
00239    0,                   /* DepthBits */
00240    0,                   /* StencilBits */
00241    0,                   /* TexelBytes */
00242    texstore_rgb_fxt1,           /* StoreTexImageFunc */
00243    NULL, /*impossible*/         /* FetchTexel1D */
00244    fetch_texel_2d_rgb_fxt1,         /* FetchTexel2D */
00245    NULL, /*impossible*/         /* FetchTexel3D */
00246    NULL, /*impossible*/         /* FetchTexel1Df */
00247    fetch_texel_2d_f_rgb_fxt1,       /* FetchTexel2Df */
00248    NULL, /*impossible*/         /* FetchTexel3Df */
00249    NULL                 /* StoreTexel */
00250 };
00251 
00252 const struct gl_texture_format _mesa_texformat_rgba_fxt1 = {
00253    MESA_FORMAT_RGBA_FXT1,       /* MesaFormat */
00254    GL_RGBA,             /* BaseFormat */
00255    GL_UNSIGNED_NORMALIZED_ARB,      /* DataType */
00256    4, /*approx*/            /* RedBits */
00257    4, /*approx*/            /* GreenBits */
00258    4, /*approx*/            /* BlueBits */
00259    1, /*approx*/            /* AlphaBits */
00260    0,                   /* LuminanceBits */
00261    0,                   /* IntensityBits */
00262    0,                   /* IndexBits */
00263    0,                   /* DepthBits */
00264    0,                   /* StencilBits */
00265    0,                   /* TexelBytes */
00266    texstore_rgba_fxt1,          /* StoreTexImageFunc */
00267    NULL, /*impossible*/         /* FetchTexel1D */
00268    fetch_texel_2d_rgba_fxt1,        /* FetchTexel2D */
00269    NULL, /*impossible*/         /* FetchTexel3D */
00270    NULL, /*impossible*/         /* FetchTexel1Df */
00271    fetch_texel_2d_f_rgba_fxt1,      /* FetchTexel2Df */
00272    NULL, /*impossible*/         /* FetchTexel3Df */
00273    NULL                 /* StoreTexel */
00274 };
00275 
00276 
00277 /***************************************************************************\
00278  * FXT1 encoder
00279  *
00280  * The encoder was built by reversing the decoder,
00281  * and is vaguely based on Texus2 by 3dfx. Note that this code
00282  * is merely a proof of concept, since it is highly UNoptimized;
00283  * moreover, it is sub-optimal due to initial conditions passed
00284  * to Lloyd's algorithm (the interpolation modes are even worse).
00285 \***************************************************************************/
00286 
00287 
00288 #define MAX_COMP 4 /* ever needed maximum number of components in texel */
00289 #define MAX_VECT 4 /* ever needed maximum number of base vectors to find */
00290 #define N_TEXELS 32 /* number of texels in a block (always 32) */
00291 #define LL_N_REP 50 /* number of iterations in lloyd's vq */
00292 #define LL_RMS_D 10 /* fault tolerance (maximum delta) */
00293 #define LL_RMS_E 255 /* fault tolerance (maximum error) */
00294 #define ALPHA_TS 2 /* alpha threshold: (255 - ALPHA_TS) deemed opaque */
00295 #define ISTBLACK(v) (*((GLuint *)(v)) == 0)
00296 
00297 
00298 /*
00299  * Define a 64-bit unsigned integer type and macros
00300  */
00301 #ifdef GL_EXT_timer_query  /* this extensions defines the GLuint64EXT type */
00302 
00303 #define FX64_NATIVE 1
00304 
00305 typedef GLuint64EXT Fx64;
00306 
00307 #define FX64_MOV32(a, b) a = b
00308 #define FX64_OR32(a, b)  a |= b
00309 #define FX64_SHL(a, c)   a <<= c
00310 
00311 #else  /* !GL_EXT_timer_query */
00312 
00313 #define FX64_NATIVE 0
00314 
00315 typedef struct {
00316    GLuint lo, hi;
00317 } Fx64;
00318 
00319 #define FX64_MOV32(a, b) a.lo = b
00320 #define FX64_OR32(a, b)  a.lo |= b
00321 
00322 #define FX64_SHL(a, c)                                 \
00323    do {                                                \
00324        if ((c) >= 32) {                                \
00325           a.hi = a.lo << ((c) - 32);                   \
00326           a.lo = 0;                                    \
00327        } else {                                        \
00328           a.hi = (a.hi << (c)) | (a.lo >> (32 - (c))); \
00329           a.lo <<= (c);                                \
00330        }                                               \
00331    } while (0)
00332 
00333 #endif  /* !GL_EXT_timer_query */
00334 
00335 
00336 #define F(i) (GLfloat)1 /* can be used to obtain an oblong metric: 0.30 / 0.59 / 0.11 */
00337 #define SAFECDOT 1 /* for paranoids */
00338 
00339 #define MAKEIVEC(NV, NC, IV, B, V0, V1)  \
00340    do {                                  \
00341       /* compute interpolation vector */ \
00342       GLfloat d2 = 0.0F;                 \
00343       GLfloat rd2;                       \
00344                                          \
00345       for (i = 0; i < NC; i++) {         \
00346          IV[i] = (V1[i] - V0[i]) * F(i); \
00347          d2 += IV[i] * IV[i];            \
00348       }                                  \
00349       rd2 = (GLfloat)NV / d2;            \
00350       B = 0;                             \
00351       for (i = 0; i < NC; i++) {         \
00352          IV[i] *= F(i);                  \
00353          B -= IV[i] * V0[i];             \
00354          IV[i] *= rd2;                   \
00355       }                                  \
00356       B = B * rd2 + 0.5f;                \
00357    } while (0)
00358 
00359 #define CALCCDOT(TEXEL, NV, NC, IV, B, V)\
00360    do {                                  \
00361       GLfloat dot = 0.0F;                \
00362       for (i = 0; i < NC; i++) {         \
00363          dot += V[i] * IV[i];            \
00364       }                                  \
00365       TEXEL = (GLint)(dot + B);          \
00366       if (SAFECDOT) {                    \
00367          if (TEXEL < 0) {                \
00368             TEXEL = 0;                   \
00369          } else if (TEXEL > NV) {        \
00370             TEXEL = NV;                  \
00371          }                               \
00372       }                                  \
00373    } while (0)
00374 
00375 
00376 static GLint
00377 fxt1_bestcol (GLfloat vec[][MAX_COMP], GLint nv,
00378               GLubyte input[MAX_COMP], GLint nc)
00379 {
00380    GLint i, j, best = -1;
00381    GLfloat err = 1e9; /* big enough */
00382 
00383    for (j = 0; j < nv; j++) {
00384       GLfloat e = 0.0F;
00385       for (i = 0; i < nc; i++) {
00386          e += (vec[j][i] - input[i]) * (vec[j][i] - input[i]);
00387       }
00388       if (e < err) {
00389          err = e;
00390          best = j;
00391       }
00392    }
00393 
00394    return best;
00395 }
00396 
00397 
00398 static GLint
00399 fxt1_worst (GLfloat vec[MAX_COMP],
00400             GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n)
00401 {
00402    GLint i, k, worst = -1;
00403    GLfloat err = -1.0F; /* small enough */
00404 
00405    for (k = 0; k < n; k++) {
00406       GLfloat e = 0.0F;
00407       for (i = 0; i < nc; i++) {
00408          e += (vec[i] - input[k][i]) * (vec[i] - input[k][i]);
00409       }
00410       if (e > err) {
00411          err = e;
00412          worst = k;
00413       }
00414    }
00415 
00416    return worst;
00417 }
00418 
00419 
00420 static GLint
00421 fxt1_variance (GLdouble variance[MAX_COMP],
00422                GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n)
00423 {
00424    GLint i, k, best = 0;
00425    GLint sx, sx2;
00426    GLdouble var, maxvar = -1; /* small enough */
00427    GLdouble teenth = 1.0 / n;
00428 
00429    for (i = 0; i < nc; i++) {
00430       sx = sx2 = 0;
00431       for (k = 0; k < n; k++) {
00432          GLint t = input[k][i];
00433          sx += t;
00434          sx2 += t * t;
00435       }
00436       var = sx2 * teenth - sx * sx * teenth * teenth;
00437       if (maxvar < var) {
00438          maxvar = var;
00439          best = i;
00440       }
00441       if (variance) {
00442          variance[i] = var;
00443       }
00444    }
00445 
00446    return best;
00447 }
00448 
00449 
00450 static GLint
00451 fxt1_choose (GLfloat vec[][MAX_COMP], GLint nv,
00452              GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n)
00453 {
00454 #if 0
00455    /* Choose colors from a grid.
00456     */
00457    GLint i, j;
00458 
00459    for (j = 0; j < nv; j++) {
00460       GLint m = j * (n - 1) / (nv - 1);
00461       for (i = 0; i < nc; i++) {
00462          vec[j][i] = input[m][i];
00463       }
00464    }
00465 #else
00466    /* Our solution here is to find the darkest and brightest colors in
00467     * the 8x4 tile and use those as the two representative colors.
00468     * There are probably better algorithms to use (histogram-based).
00469     */
00470    GLint i, j, k;
00471    GLint minSum = 2000; /* big enough */
00472    GLint maxSum = -1; /* small enough */
00473    GLint minCol = 0; /* phoudoin: silent compiler! */
00474    GLint maxCol = 0; /* phoudoin: silent compiler! */
00475 
00476    struct {
00477       GLint flag;
00478       GLint key;
00479       GLint freq;
00480       GLint idx;
00481    } hist[N_TEXELS];
00482    GLint lenh = 0;
00483 
00484    _mesa_memset(hist, 0, sizeof(hist));
00485 
00486    for (k = 0; k < n; k++) {
00487       GLint l;
00488       GLint key = 0;
00489       GLint sum = 0;
00490       for (i = 0; i < nc; i++) {
00491          key <<= 8;
00492          key |= input[k][i];
00493          sum += input[k][i];
00494       }
00495       for (l = 0; l < n; l++) {
00496          if (!hist[l].flag) {
00497             /* alloc new slot */
00498             hist[l].flag = !0;
00499             hist[l].key = key;
00500             hist[l].freq = 1;
00501             hist[l].idx = k;
00502             lenh = l + 1;
00503             break;
00504          } else if (hist[l].key == key) {
00505             hist[l].freq++;
00506             break;
00507          }
00508       }
00509       if (minSum > sum) {
00510          minSum = sum;
00511          minCol = k;
00512       }
00513       if (maxSum < sum) {
00514          maxSum = sum;
00515          maxCol = k;
00516       }
00517    }
00518 
00519    if (lenh <= nv) {
00520       for (j = 0; j < lenh; j++) {
00521          for (i = 0; i < nc; i++) {
00522             vec[j][i] = (GLfloat)input[hist[j].idx][i];
00523          }
00524       }
00525       for (; j < nv; j++) {
00526          for (i = 0; i < nc; i++) {
00527             vec[j][i] = vec[0][i];
00528          }
00529       }
00530       return 0;
00531    }
00532 
00533    for (j = 0; j < nv; j++) {
00534       for (i = 0; i < nc; i++) {
00535          vec[j][i] = ((nv - 1 - j) * input[minCol][i] + j * input[maxCol][i] + (nv - 1) / 2) / (GLfloat)(nv - 1);
00536       }
00537    }
00538 #endif
00539 
00540    return !0;
00541 }
00542 
00543 
00544 static GLint
00545 fxt1_lloyd (GLfloat vec[][MAX_COMP], GLint nv,
00546             GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n)
00547 {
00548    /* Use the generalized lloyd's algorithm for VQ:
00549     *     find 4 color vectors.
00550     *
00551     *     for each sample color
00552     *         sort to nearest vector.
00553     *
00554     *     replace each vector with the centroid of it's matching colors.
00555     *
00556     *     repeat until RMS doesn't improve.
00557     *
00558     *     if a color vector has no samples, or becomes the same as another
00559     *     vector, replace it with the color which is farthest from a sample.
00560     *
00561     * vec[][MAX_COMP]           initial vectors and resulting colors
00562     * nv                        number of resulting colors required
00563     * input[N_TEXELS][MAX_COMP] input texels
00564     * nc                        number of components in input / vec
00565     * n                         number of input samples
00566     */
00567 
00568    GLint sum[MAX_VECT][MAX_COMP]; /* used to accumulate closest texels */
00569    GLint cnt[MAX_VECT]; /* how many times a certain vector was chosen */
00570    GLfloat error, lasterror = 1e9;
00571 
00572    GLint i, j, k, rep;
00573 
00574    /* the quantizer */
00575    for (rep = 0; rep < LL_N_REP; rep++) {
00576       /* reset sums & counters */
00577       for (j = 0; j < nv; j++) {
00578          for (i = 0; i < nc; i++) {
00579             sum[j][i] = 0;
00580          }
00581          cnt[j] = 0;
00582       }
00583       error = 0;
00584 
00585       /* scan whole block */
00586       for (k = 0; k < n; k++) {
00587 #if 1
00588          GLint best = -1;
00589          GLfloat err = 1e9; /* big enough */
00590          /* determine best vector */
00591          for (j = 0; j < nv; j++) {
00592             GLfloat e = (vec[j][0] - input[k][0]) * (vec[j][0] - input[k][0]) +
00593                       (vec[j][1] - input[k][1]) * (vec[j][1] - input[k][1]) +
00594                       (vec[j][2] - input[k][2]) * (vec[j][2] - input[k][2]);
00595             if (nc == 4) {
00596                e += (vec[j][3] - input[k][3]) * (vec[j][3] - input[k][3]);
00597             }
00598             if (e < err) {
00599                err = e;
00600                best = j;
00601             }
00602          }
00603 #else
00604          GLint best = fxt1_bestcol(vec, nv, input[k], nc, &err);
00605 #endif
00606          /* add in closest color */
00607          for (i = 0; i < nc; i++) {
00608             sum[best][i] += input[k][i];
00609          }
00610          /* mark this vector as used */
00611          cnt[best]++;
00612          /* accumulate error */
00613          error += err;
00614       }
00615 
00616       /* check RMS */
00617       if ((error < LL_RMS_E) ||
00618           ((error < lasterror) && ((lasterror - error) < LL_RMS_D))) {
00619          return !0; /* good match */
00620       }
00621       lasterror = error;
00622 
00623       /* move each vector to the barycenter of its closest colors */
00624       for (j = 0; j < nv; j++) {
00625          if (cnt[j]) {
00626             GLfloat div = 1.0F / cnt[j];
00627             for (i = 0; i < nc; i++) {
00628                vec[j][i] = div * sum[j][i];
00629             }
00630          } else {
00631             /* this vec has no samples or is identical with a previous vec */
00632             GLint worst = fxt1_worst(vec[j], input, nc, n);
00633             for (i = 0; i < nc; i++) {
00634                vec[j][i] = input[worst][i];
00635             }
00636          }
00637       }
00638    }
00639 
00640    return 0; /* could not converge fast enough */
00641 }
00642 
00643 
00644 static void
00645 fxt1_quantize_CHROMA (GLuint *cc,
00646                       GLubyte input[N_TEXELS][MAX_COMP])
00647 {
00648    const GLint n_vect = 4; /* 4 base vectors to find */
00649    const GLint n_comp = 3; /* 3 components: R, G, B */
00650    GLfloat vec[MAX_VECT][MAX_COMP];
00651    GLint i, j, k;
00652    Fx64 hi; /* high quadword */
00653    GLuint lohi, lolo; /* low quadword: hi dword, lo dword */
00654 
00655    if (fxt1_choose(vec, n_vect, input, n_comp, N_TEXELS) != 0) {
00656       fxt1_lloyd(vec, n_vect, input, n_comp, N_TEXELS);
00657    }
00658 
00659    FX64_MOV32(hi, 4); /* cc-chroma = "010" + unused bit */
00660    for (j = n_vect - 1; j >= 0; j--) {
00661       for (i = 0; i < n_comp; i++) {
00662          /* add in colors */
00663          FX64_SHL(hi, 5);
00664          FX64_OR32(hi, (GLuint)(vec[j][i] / 8.0F));
00665       }
00666    }
00667    ((Fx64 *)cc)[1] = hi;
00668 
00669    lohi = lolo = 0;
00670    /* right microtile */
00671    for (k = N_TEXELS - 1; k >= N_TEXELS/2; k--) {
00672       lohi <<= 2;
00673       lohi |= fxt1_bestcol(vec, n_vect, input[k], n_comp);
00674    }
00675    /* left microtile */
00676    for (; k >= 0; k--) {
00677       lolo <<= 2;
00678       lolo |= fxt1_bestcol(vec, n_vect, input[k], n_comp);
00679    }
00680    cc[1] = lohi;
00681    cc[0] = lolo;
00682 }
00683 
00684 
00685 static void
00686 fxt1_quantize_ALPHA0 (GLuint *cc,
00687                       GLubyte input[N_TEXELS][MAX_COMP],
00688                       GLubyte reord[N_TEXELS][MAX_COMP], GLint n)
00689 {
00690    const GLint n_vect = 3; /* 3 base vectors to find */
00691    const GLint n_comp = 4; /* 4 components: R, G, B, A */
00692    GLfloat vec[MAX_VECT][MAX_COMP];
00693    GLint i, j, k;
00694    Fx64 hi; /* high quadword */
00695    GLuint lohi, lolo; /* low quadword: hi dword, lo dword */
00696 
00697    /* the last vector indicates zero */
00698    for (i = 0; i < n_comp; i++) {
00699       vec[n_vect][i] = 0;
00700    }
00701 
00702    /* the first n texels in reord are guaranteed to be non-zero */
00703    if (fxt1_choose(vec, n_vect, reord, n_comp, n) != 0) {
00704       fxt1_lloyd(vec, n_vect, reord, n_comp, n);
00705    }
00706 
00707    FX64_MOV32(hi, 6); /* alpha = "011" + lerp = 0 */
00708    for (j = n_vect - 1; j >= 0; j--) {
00709       /* add in alphas */
00710       FX64_SHL(hi, 5);
00711       FX64_OR32(hi, (GLuint)(vec[j][ACOMP] / 8.0F));
00712    }
00713    for (j = n_vect - 1; j >= 0; j--) {
00714       for (i = 0; i < n_comp - 1; i++) {
00715          /* add in colors */
00716          FX64_SHL(hi, 5);
00717          FX64_OR32(hi, (GLuint)(vec[j][i] / 8.0F));
00718       }
00719    }
00720    ((Fx64 *)cc)[1] = hi;
00721 
00722    lohi = lolo = 0;
00723    /* right microtile */
00724    for (k = N_TEXELS - 1; k >= N_TEXELS/2; k--) {
00725       lohi <<= 2;
00726       lohi |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp);
00727    }
00728    /* left microtile */
00729    for (; k >= 0; k--) {
00730       lolo <<= 2;
00731       lolo |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp);
00732    }
00733    cc[1] = lohi;
00734    cc[0] = lolo;
00735 }
00736 
00737 
00738 static void
00739 fxt1_quantize_ALPHA1 (GLuint *cc,
00740                       GLubyte input[N_TEXELS][MAX_COMP])
00741 {
00742    const GLint n_vect = 3; /* highest vector number in each microtile */
00743    const GLint n_comp = 4; /* 4 components: R, G, B, A */
00744    GLfloat vec[1 + 1 + 1][MAX_COMP]; /* 1.5 extrema for each sub-block */
00745    GLfloat b, iv[MAX_COMP]; /* interpolation vector */
00746    GLint i, j, k;
00747    Fx64 hi; /* high quadword */
00748    GLuint lohi, lolo; /* low quadword: hi dword, lo dword */
00749 
00750    GLint minSum;
00751    GLint maxSum;
00752    GLint minColL = 0, maxColL = 0;
00753    GLint minColR = 0, maxColR = 0;
00754    GLint sumL = 0, sumR = 0;
00755    GLint nn_comp;
00756    /* Our solution here is to find the darkest and brightest colors in
00757     * the 4x4 tile and use those as the two representative colors.
00758     * There are probably better algorithms to use (histogram-based).
00759     */
00760    nn_comp = n_comp;
00761    while ((minColL == maxColL) && nn_comp) {
00762        minSum = 2000; /* big enough */
00763        maxSum = -1; /* small enough */
00764        for (k = 0; k < N_TEXELS / 2; k++) {
00765            GLint sum = 0;
00766            for (i = 0; i < nn_comp; i++) {
00767                sum += input[k][i];
00768            }
00769            if (minSum > sum) {
00770                minSum = sum;
00771                minColL = k;
00772            }
00773            if (maxSum < sum) {
00774                maxSum = sum;
00775                maxColL = k;
00776            }
00777            sumL += sum;
00778        }
00779        
00780        nn_comp--;
00781    }
00782 
00783    nn_comp = n_comp;
00784    while ((minColR == maxColR) && nn_comp) {
00785        minSum = 2000; /* big enough */
00786        maxSum = -1; /* small enough */
00787        for (k = N_TEXELS / 2; k < N_TEXELS; k++) {
00788            GLint sum = 0;
00789            for (i = 0; i < nn_comp; i++) {
00790                sum += input[k][i];
00791            }
00792            if (minSum > sum) {
00793                minSum = sum;
00794                minColR = k;
00795            }
00796            if (maxSum < sum) {
00797                maxSum = sum;
00798                maxColR = k;
00799            }
00800            sumR += sum;
00801        }
00802 
00803        nn_comp--;
00804    }
00805 
00806    /* choose the common vector (yuck!) */
00807    {
00808       GLint j1, j2;
00809       GLint v1 = 0, v2 = 0;
00810       GLfloat err = 1e9; /* big enough */
00811       GLfloat tv[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */
00812       for (i = 0; i < n_comp; i++) {
00813          tv[0][i] = input[minColL][i];
00814          tv[1][i] = input[maxColL][i];
00815          tv[2][i] = input[minColR][i];
00816          tv[3][i] = input[maxColR][i];
00817       }
00818       for (j1 = 0; j1 < 2; j1++) {
00819          for (j2 = 2; j2 < 4; j2++) {
00820             GLfloat e = 0.0F;
00821             for (i = 0; i < n_comp; i++) {
00822                e += (tv[j1][i] - tv[j2][i]) * (tv[j1][i] - tv[j2][i]);
00823             }
00824             if (e < err) {
00825                err = e;
00826                v1 = j1;
00827                v2 = j2;
00828             }
00829          }
00830       }
00831       for (i = 0; i < n_comp; i++) {
00832          vec[0][i] = tv[1 - v1][i];
00833          vec[1][i] = (tv[v1][i] * sumL + tv[v2][i] * sumR) / (sumL + sumR);
00834          vec[2][i] = tv[5 - v2][i];
00835       }
00836    }
00837 
00838    /* left microtile */
00839    cc[0] = 0;
00840    if (minColL != maxColL) {
00841       /* compute interpolation vector */
00842       MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
00843 
00844       /* add in texels */
00845       lolo = 0;
00846       for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
00847          GLint texel;
00848          /* interpolate color */
00849          CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
00850          /* add in texel */
00851          lolo <<= 2;
00852          lolo |= texel;
00853       }
00854       
00855       cc[0] = lolo;
00856    }
00857 
00858    /* right microtile */
00859    cc[1] = 0;
00860    if (minColR != maxColR) {
00861       /* compute interpolation vector */
00862       MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[1]);
00863 
00864       /* add in texels */
00865       lohi = 0;
00866       for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
00867          GLint texel;
00868          /* interpolate color */
00869          CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
00870          /* add in texel */
00871          lohi <<= 2;
00872          lohi |= texel;
00873       }
00874 
00875       cc[1] = lohi;
00876    }
00877 
00878    FX64_MOV32(hi, 7); /* alpha = "011" + lerp = 1 */
00879    for (j = n_vect - 1; j >= 0; j--) {
00880       /* add in alphas */
00881       FX64_SHL(hi, 5);
00882       FX64_OR32(hi, (GLuint)(vec[j][ACOMP] / 8.0F));
00883    }
00884    for (j = n_vect - 1; j >= 0; j--) {
00885       for (i = 0; i < n_comp - 1; i++) {
00886          /* add in colors */
00887          FX64_SHL(hi, 5);
00888          FX64_OR32(hi, (GLuint)(vec[j][i] / 8.0F));
00889       }
00890    }
00891    ((Fx64 *)cc)[1] = hi;
00892 }
00893 
00894 
00895 static void
00896 fxt1_quantize_HI (GLuint *cc,
00897                   GLubyte input[N_TEXELS][MAX_COMP],
00898                   GLubyte reord[N_TEXELS][MAX_COMP], GLint n)
00899 {
00900    const GLint n_vect = 6; /* highest vector number */
00901    const GLint n_comp = 3; /* 3 components: R, G, B */
00902    GLfloat b = 0.0F;       /* phoudoin: silent compiler! */
00903    GLfloat iv[MAX_COMP];   /* interpolation vector */
00904    GLint i, k;
00905    GLuint hihi; /* high quadword: hi dword */
00906 
00907    GLint minSum = 2000; /* big enough */
00908    GLint maxSum = -1; /* small enough */
00909    GLint minCol = 0; /* phoudoin: silent compiler! */
00910    GLint maxCol = 0; /* phoudoin: silent compiler! */
00911 
00912    /* Our solution here is to find the darkest and brightest colors in
00913     * the 8x4 tile and use those as the two representative colors.
00914     * There are probably better algorithms to use (histogram-based).
00915     */
00916    for (k = 0; k < n; k++) {
00917       GLint sum = 0;
00918       for (i = 0; i < n_comp; i++) {
00919          sum += reord[k][i];
00920       }
00921       if (minSum > sum) {
00922          minSum = sum;
00923          minCol = k;
00924       }
00925       if (maxSum < sum) {
00926          maxSum = sum;
00927          maxCol = k;
00928       }
00929    }
00930 
00931    hihi = 0; /* cc-hi = "00" */
00932    for (i = 0; i < n_comp; i++) {
00933       /* add in colors */
00934       hihi <<= 5;
00935       hihi |= reord[maxCol][i] >> 3;
00936    }
00937    for (i = 0; i < n_comp; i++) {
00938       /* add in colors */
00939       hihi <<= 5;
00940       hihi |= reord[minCol][i] >> 3;
00941    }
00942    cc[3] = hihi;
00943    cc[0] = cc[1] = cc[2] = 0;
00944 
00945    /* compute interpolation vector */
00946    if (minCol != maxCol) {
00947       MAKEIVEC(n_vect, n_comp, iv, b, reord[minCol], reord[maxCol]);
00948    }
00949 
00950    /* add in texels */
00951    for (k = N_TEXELS - 1; k >= 0; k--) {
00952       GLint t = k * 3;
00953       GLuint *kk = (GLuint *)((char *)cc + t / 8);
00954       GLint texel = n_vect + 1; /* transparent black */
00955 
00956       if (!ISTBLACK(input[k])) {
00957          if (minCol != maxCol) {
00958             /* interpolate color */
00959             CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
00960             /* add in texel */
00961             kk[0] |= texel << (t & 7);
00962          }
00963       } else {
00964          /* add in texel */
00965          kk[0] |= texel << (t & 7);
00966       }
00967    }
00968 }
00969 
00970 
00971 static void
00972 fxt1_quantize_MIXED1 (GLuint *cc,
00973                       GLubyte input[N_TEXELS][MAX_COMP])
00974 {
00975    const GLint n_vect = 2; /* highest vector number in each microtile */
00976    const GLint n_comp = 3; /* 3 components: R, G, B */
00977    GLubyte vec[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */
00978    GLfloat b, iv[MAX_COMP]; /* interpolation vector */
00979    GLint i, j, k;
00980    Fx64 hi; /* high quadword */
00981    GLuint lohi, lolo; /* low quadword: hi dword, lo dword */
00982 
00983    GLint minSum;
00984    GLint maxSum;
00985    GLint minColL = 0, maxColL = -1;
00986    GLint minColR = 0, maxColR = -1;
00987 
00988    /* Our solution here is to find the darkest and brightest colors in
00989     * the 4x4 tile and use those as the two representative colors.
00990     * There are probably better algorithms to use (histogram-based).
00991     */
00992    minSum = 2000; /* big enough */
00993    maxSum = -1; /* small enough */
00994    for (k = 0; k < N_TEXELS / 2; k++) {
00995       if (!ISTBLACK(input[k])) {
00996          GLint sum = 0;
00997          for (i = 0; i < n_comp; i++) {
00998             sum += input[k][i];
00999          }
01000          if (minSum > sum) {
01001             minSum = sum;
01002             minColL = k;
01003          }
01004          if (maxSum < sum) {
01005             maxSum = sum;
01006             maxColL = k;
01007          }
01008       }
01009    }
01010    minSum = 2000; /* big enough */
01011    maxSum = -1; /* small enough */
01012    for (; k < N_TEXELS; k++) {
01013       if (!ISTBLACK(input[k])) {
01014          GLint sum = 0;
01015          for (i = 0; i < n_comp; i++) {
01016             sum += input[k][i];
01017          }
01018          if (minSum > sum) {
01019             minSum = sum;
01020             minColR = k;
01021          }
01022          if (maxSum < sum) {
01023             maxSum = sum;
01024             maxColR = k;
01025          }
01026       }
01027    }
01028 
01029    /* left microtile */
01030    if (maxColL == -1) {
01031       /* all transparent black */
01032       cc[0] = ~0u;
01033       for (i = 0; i < n_comp; i++) {
01034          vec[0][i] = 0;
01035          vec[1][i] = 0;
01036       }
01037    } else {
01038       cc[0] = 0;
01039       for (i = 0; i < n_comp; i++) {
01040          vec[0][i] = input[minColL][i];
01041          vec[1][i] = input[maxColL][i];
01042       }
01043       if (minColL != maxColL) {
01044          /* compute interpolation vector */
01045          MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
01046 
01047          /* add in texels */
01048          lolo = 0;
01049          for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
01050             GLint texel = n_vect + 1; /* transparent black */
01051             if (!ISTBLACK(input[k])) {
01052                /* interpolate color */
01053                CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
01054             }
01055             /* add in texel */
01056             lolo <<= 2;
01057             lolo |= texel;
01058          }
01059          cc[0] = lolo;
01060       }
01061    }
01062 
01063    /* right microtile */
01064    if (maxColR == -1) {
01065       /* all transparent black */
01066       cc[1] = ~0u;
01067       for (i = 0; i < n_comp; i++) {
01068          vec[2][i] = 0;
01069          vec[3][i] = 0;
01070       }
01071    } else {
01072       cc[1] = 0;
01073       for (i = 0; i < n_comp; i++) {
01074          vec[2][i] = input[minColR][i];
01075          vec[3][i] = input[maxColR][i];
01076       }
01077       if (minColR != maxColR) {
01078          /* compute interpolation vector */
01079          MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]);
01080 
01081          /* add in texels */
01082          lohi = 0;
01083          for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
01084             GLint texel = n_vect + 1; /* transparent black */
01085             if (!ISTBLACK(input[k])) {
01086                /* interpolate color */
01087                CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
01088             }
01089             /* add in texel */
01090             lohi <<= 2;
01091             lohi |= texel;
01092          }
01093          cc[1] = lohi;
01094       }
01095    }
01096 
01097    FX64_MOV32(hi, 9 | (vec[3][GCOMP] & 4) | ((vec[1][GCOMP] >> 1) & 2)); /* chroma = "1" */
01098    for (j = 2 * 2 - 1; j >= 0; j--) {
01099       for (i = 0; i < n_comp; i++) {
01100          /* add in colors */
01101          FX64_SHL(hi, 5);
01102          FX64_OR32(hi, vec[j][i] >> 3);
01103       }
01104    }
01105    ((Fx64 *)cc)[1] = hi;
01106 }
01107 
01108 
01109 static void
01110 fxt1_quantize_MIXED0 (GLuint *cc,
01111                       GLubyte input[N_TEXELS][MAX_COMP])
01112 {
01113    const GLint n_vect = 3; /* highest vector number in each microtile */
01114    const GLint n_comp = 3; /* 3 components: R, G, B */
01115    GLubyte vec[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */
01116    GLfloat b, iv[MAX_COMP]; /* interpolation vector */
01117    GLint i, j, k;
01118    Fx64 hi; /* high quadword */
01119    GLuint lohi, lolo; /* low quadword: hi dword, lo dword */
01120 
01121    GLint minColL = 0, maxColL = 0;
01122    GLint minColR = 0, maxColR = 0;
01123 #if 0
01124    GLint minSum;
01125    GLint maxSum;
01126 
01127    /* Our solution here is to find the darkest and brightest colors in
01128     * the 4x4 tile and use those as the two representative colors.
01129     * There are probably better algorithms to use (histogram-based).
01130     */
01131    minSum = 2000; /* big enough */
01132    maxSum = -1; /* small enough */
01133    for (k = 0; k < N_TEXELS / 2; k++) {
01134       GLint sum = 0;
01135       for (i = 0; i < n_comp; i++) {
01136          sum += input[k][i];
01137       }
01138       if (minSum > sum) {
01139          minSum = sum;
01140          minColL = k;
01141       }
01142       if (maxSum < sum) {
01143          maxSum = sum;
01144          maxColL = k;
01145       }
01146    }
01147    minSum = 2000; /* big enough */
01148    maxSum = -1; /* small enough */
01149    for (; k < N_TEXELS; k++) {
01150       GLint sum = 0;
01151       for (i = 0; i < n_comp; i++) {
01152          sum += input[k][i];
01153       }
01154       if (minSum > sum) {
01155          minSum = sum;
01156          minColR = k;
01157       }
01158       if (maxSum < sum) {
01159          maxSum = sum;
01160          maxColR = k;
01161       }
01162    }
01163 #else
01164    GLint minVal;
01165    GLint maxVal;
01166    GLint maxVarL = fxt1_variance(NULL, input, n_comp, N_TEXELS / 2);
01167    GLint maxVarR = fxt1_variance(NULL, &input[N_TEXELS / 2], n_comp, N_TEXELS / 2);
01168 
01169    /* Scan the channel with max variance for lo & hi
01170     * and use those as the two representative colors.
01171     */
01172    minVal = 2000; /* big enough */
01173    maxVal = -1; /* small enough */
01174    for (k = 0; k < N_TEXELS / 2; k++) {
01175       GLint t = input[k][maxVarL];
01176       if (minVal > t) {
01177          minVal = t;
01178          minColL = k;
01179       }
01180       if (maxVal < t) {
01181          maxVal = t;
01182          maxColL = k;
01183       }
01184    }
01185    minVal = 2000; /* big enough */
01186    maxVal = -1; /* small enough */
01187    for (; k < N_TEXELS; k++) {
01188       GLint t = input[k][maxVarR];
01189       if (minVal > t) {
01190          minVal = t;
01191          minColR = k;
01192       }
01193       if (maxVal < t) {
01194          maxVal = t;
01195          maxColR = k;
01196       }
01197    }
01198 #endif
01199 
01200    /* left microtile */
01201    cc[0] = 0;
01202    for (i = 0; i < n_comp; i++) {
01203       vec[0][i] = input[minColL][i];
01204       vec[1][i] = input[maxColL][i];
01205    }
01206    if (minColL != maxColL) {
01207       /* compute interpolation vector */
01208       MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]);
01209 
01210       /* add in texels */
01211       lolo = 0;
01212       for (k = N_TEXELS / 2 - 1; k >= 0; k--) {
01213          GLint texel;
01214          /* interpolate color */
01215          CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
01216          /* add in texel */
01217          lolo <<= 2;
01218          lolo |= texel;
01219       }
01220 
01221       /* funky encoding for LSB of green */
01222       if ((GLint)((lolo >> 1) & 1) != (((vec[1][GCOMP] ^ vec[0][GCOMP]) >> 2) & 1)) {
01223          for (i = 0; i < n_comp; i++) {
01224             vec[1][i] = input[minColL][i];
01225             vec[0][i] = input[maxColL][i];
01226          }
01227          lolo = ~lolo;
01228       }
01229       
01230       cc[0] = lolo;
01231    }
01232 
01233    /* right microtile */
01234    cc[1] = 0;
01235    for (i = 0; i < n_comp; i++) {
01236       vec[2][i] = input[minColR][i];
01237       vec[3][i] = input[maxColR][i];
01238    }
01239    if (minColR != maxColR) {
01240       /* compute interpolation vector */
01241       MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]);
01242 
01243       /* add in texels */
01244       lohi = 0;
01245       for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) {
01246          GLint texel;
01247          /* interpolate color */
01248          CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]);
01249          /* add in texel */
01250          lohi <<= 2;
01251          lohi |= texel;
01252       }
01253 
01254       /* funky encoding for LSB of green */
01255       if ((GLint)((lohi >> 1) & 1) != (((vec[3][GCOMP] ^ vec[2][GCOMP]) >> 2) & 1)) {
01256          for (i = 0; i < n_comp; i++) {
01257             vec[3][i] = input[minColR][i];
01258             vec[2][i] = input[maxColR][i];
01259          }
01260          lohi = ~lohi;
01261       }
01262 
01263       cc[1] = lohi;
01264    }
01265 
01266    FX64_MOV32(hi, 8 | (vec[3][GCOMP] & 4) | ((vec[1][GCOMP] >> 1) & 2)); /* chroma = "1" */
01267    for (j = 2 * 2 - 1; j >= 0; j--) {
01268       for (i = 0; i < n_comp; i++) {
01269          /* add in colors */
01270          FX64_SHL(hi, 5);
01271          FX64_OR32(hi, vec[j][i] >> 3);
01272       }
01273    }
01274    ((Fx64 *)cc)[1] = hi;
01275 }
01276 
01277 
01278 static void
01279 fxt1_quantize (GLuint *cc, const GLubyte *lines[], GLint comps)
01280 {
01281    GLint trualpha;
01282    GLubyte reord[N_TEXELS][MAX_COMP];
01283 
01284    GLubyte input[N_TEXELS][MAX_COMP];
01285    GLint i, k, l;
01286 
01287    if (comps == 3) {
01288       /* make the whole block opaque */
01289       _mesa_memset(input, -1, sizeof(input));
01290    }
01291 
01292    /* 8 texels each line */
01293    for (l = 0; l < 4; l++) {
01294       for (k = 0; k < 4; k++) {
01295          for (i = 0; i < comps; i++) {
01296             input[k + l * 4][i] = *lines[l]++;
01297          }
01298       }
01299       for (; k < 8; k++) {
01300          for (i = 0; i < comps; i++) {
01301             input[k + l * 4 + 12][i] = *lines[l]++;
01302          }
01303       }
01304    }
01305 
01306    /* block layout:
01307     * 00, 01, 02, 03, 08, 09, 0a, 0b
01308     * 10, 11, 12, 13, 18, 19, 1a, 1b
01309     * 04, 05, 06, 07, 0c, 0d, 0e, 0f
01310     * 14, 15, 16, 17, 1c, 1d, 1e, 1f
01311     */
01312 
01313    /* [dBorca]
01314     * stupidity flows forth from this
01315     */
01316    l = N_TEXELS;
01317    trualpha = 0;
01318    if (comps == 4) {
01319       /* skip all transparent black texels */
01320       l = 0;
01321       for (k = 0; k < N_TEXELS; k++) {
01322          /* test all components against 0 */
01323          if (!ISTBLACK(input[k])) {
01324             /* texel is not transparent black */
01325             COPY_4UBV(reord[l], input[k]);
01326             if (reord[l][ACOMP] < (255 - ALPHA_TS)) {
01327                /* non-opaque texel */
01328                trualpha = !0;
01329             }
01330             l++;
01331          }
01332       }
01333    }
01334 
01335 #if 0
01336    if (trualpha) {
01337       fxt1_quantize_ALPHA0(cc, input, reord, l);
01338    } else if (l == 0) {
01339       cc[0] = cc[1] = cc[2] = -1;
01340       cc[3] = 0;
01341    } else if (l < N_TEXELS) {
01342       fxt1_quantize_HI(cc, input, reord, l);
01343    } else {
01344       fxt1_quantize_CHROMA(cc, input);
01345    }
01346    (void)fxt1_quantize_ALPHA1;
01347    (void)fxt1_quantize_MIXED1;
01348    (void)fxt1_quantize_MIXED0;
01349 #else
01350    if (trualpha) {
01351       fxt1_quantize_ALPHA1(cc, input);
01352    } else if (l == 0) {
01353       cc[0] = cc[1] = cc[2] = ~0u;
01354       cc[3] = 0;
01355    } else if (l < N_TEXELS) {
01356       fxt1_quantize_MIXED1(cc, input);
01357    } else {
01358       fxt1_quantize_MIXED0(cc, input);
01359    }
01360    (void)fxt1_quantize_ALPHA0;
01361    (void)fxt1_quantize_HI;
01362    (void)fxt1_quantize_CHROMA;
01363 #endif
01364 }
01365 
01366 
01367 static void
01368 fxt1_encode (GLuint width, GLuint height, GLint comps,
01369              const void *source, GLint srcRowStride,
01370              void *dest, GLint destRowStride)
01371 {
01372    GLuint x, y;
01373    const GLubyte *data;
01374    GLuint *encoded = (GLuint *)dest;
01375    void *newSource = NULL;
01376 
01377    assert(comps == 3 || comps == 4);
01378 
01379    /* Replicate image if width is not M8 or height is not M4 */
01380    if ((width & 7) | (height & 3)) {
01381       GLint newWidth = (width + 7) & ~7;
01382       GLint newHeight = (height + 3) & ~3;
01383       newSource = _mesa_malloc(comps * newWidth * newHeight * sizeof(GLchan));
01384       if (!newSource) {
01385          GET_CURRENT_CONTEXT(ctx);
01386          _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture compression");
01387          goto cleanUp;
01388       }
01389       _mesa_upscale_teximage2d(width, height, newWidth, newHeight,
01390                                comps, (const GLchan *) source,
01391                                srcRowStride, (GLchan *) newSource);
01392       source = newSource;
01393       width = newWidth;
01394       height = newHeight;
01395       srcRowStride = comps * newWidth;
01396    }
01397 
01398    /* convert from 16/32-bit channels to GLubyte if needed */
01399    if (CHAN_TYPE != GL_UNSIGNED_BYTE) {
01400       const GLuint n = width * height * comps;
01401       const GLchan *src = (const GLchan *) source;
01402       GLubyte *dest = (GLubyte *) _mesa_malloc(n * sizeof(GLubyte));
01403       GLuint i;
01404       if (!dest) {
01405          GET_CURRENT_CONTEXT(ctx);
01406          _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture compression");
01407          goto cleanUp;
01408       }
01409       for (i = 0; i < n; i++) {
01410          dest[i] = CHAN_TO_UBYTE(src[i]);
01411       }
01412       if (newSource != NULL) {
01413          _mesa_free(newSource);
01414       }
01415       newSource = dest;  /* we'll free this buffer before returning */
01416       source = dest;  /* the new, GLubyte incoming image */
01417    }
01418 
01419    data = (const GLubyte *) source;
01420    destRowStride = (destRowStride - width * 2) / 4;
01421    for (y = 0; y < height; y += 4) {
01422       GLuint offs = 0 + (y + 0) * srcRowStride;
01423       for (x = 0; x < width; x += 8) {
01424          const GLubyte *lines[4];
01425          lines[0] = &data[offs];
01426          lines[1] = lines[0] + srcRowStride;
01427          lines[2] = lines[1] + srcRowStride;
01428          lines[3] = lines[2] + srcRowStride;
01429          offs += 8 * comps;
01430          fxt1_quantize(encoded, lines, comps);
01431          /* 128 bits per 8x4 block */
01432          encoded += 4;
01433       }
01434       encoded += destRowStride;
01435    }
01436 
01437  cleanUp:
01438    if (newSource != NULL) {
01439       _mesa_free(newSource);
01440    }
01441 }
01442 
01443 
01444 /***************************************************************************\
01445  * FXT1 decoder
01446  *
01447  * The decoder is based on GL_3DFX_texture_compression_FXT1
01448  * specification and serves as a concept for the encoder.
01449 \***************************************************************************/
01450 
01451 
01452 /* lookup table for scaling 5 bit colors up to 8 bits */
01453 static const GLubyte _rgb_scale_5[] = {
01454    0,   8,   16,  25,  33,  41,  49,  58,
01455    66,  74,  82,  90,  99,  107, 115, 123,
01456    132, 140, 148, 156, 165, 173, 181, 189,
01457    197, 206, 214, 222, 230, 239, 247, 255
01458 };
01459 
01460 /* lookup table for scaling 6 bit colors up to 8 bits */
01461 static const GLubyte _rgb_scale_6[] = {
01462    0,   4,   8,   12,  16,  20,  24,  28,
01463    32,  36,  40,  45,  49,  53,  57,  61,
01464    65,  69,  73,  77,  81,  85,  89,  93,
01465    97,  101, 105, 109, 113, 117, 121, 125,
01466    130, 134, 138, 142, 146, 150, 154, 158,
01467    162, 166, 170, 174, 178, 182, 186, 190,
01468    194, 198, 202, 206, 210, 215, 219, 223,
01469    227, 231, 235, 239, 243, 247, 251, 255
01470 };
01471 
01472 
01473 #define CC_SEL(cc, which) (((GLuint *)(cc))[(which) / 32] >> ((which) & 31))
01474 #define UP5(c) _rgb_scale_5[(c) & 31]
01475 #define UP6(c, b) _rgb_scale_6[(((c) & 31) << 1) | ((b) & 1)]
01476 #define LERP(n, t, c0, c1) (((n) - (t)) * (c0) + (t) * (c1) + (n) / 2) / (n)
01477 
01478 
01479 static void
01480 fxt1_decode_1HI (const GLubyte *code, GLint t, GLchan *rgba)
01481 {
01482    const GLuint *cc;
01483 
01484    t *= 3;
01485    cc = (const GLuint *)(code + t / 8);
01486    t = (cc[0] >> (t & 7)) & 7;
01487 
01488    if (t == 7) {
01489       rgba[RCOMP] = rgba[GCOMP] = rgba[BCOMP] = rgba[ACOMP] = 0;
01490    } else {
01491       GLubyte r, g, b;
01492       cc = (const GLuint *)(code + 12);
01493       if (t == 0) {
01494          b = UP5(CC_SEL(cc, 0));
01495          g = UP5(CC_SEL(cc, 5));
01496          r = UP5(CC_SEL(cc, 10));
01497       } else if (t == 6) {
01498          b = UP5(CC_SEL(cc, 15));
01499          g = UP5(CC_SEL(cc, 20));
01500          r = UP5(CC_SEL(cc, 25));
01501       } else {
01502          b = LERP(6, t, UP5(CC_SEL(cc, 0)), UP5(CC_SEL(cc, 15)));
01503          g = LERP(6, t, UP5(CC_SEL(cc, 5)), UP5(CC_SEL(cc, 20)));
01504          r = LERP(6, t, UP5(CC_SEL(cc, 10)), UP5(CC_SEL(cc, 25)));
01505       }
01506       rgba[RCOMP] = UBYTE_TO_CHAN(r);
01507       rgba[GCOMP] = UBYTE_TO_CHAN(g);
01508       rgba[BCOMP] = UBYTE_TO_CHAN(b);
01509       rgba[ACOMP] = CHAN_MAX;
01510    }
01511 }
01512 
01513 
01514 static void
01515 fxt1_decode_1CHROMA (const GLubyte *code, GLint t, GLchan *rgba)
01516 {
01517    const GLuint *cc;
01518    GLuint kk;
01519 
01520    cc = (const GLuint *)code;
01521    if (t & 16) {
01522       cc++;
01523       t &= 15;
01524    }
01525    t = (cc[0] >> (t * 2)) & 3;
01526 
01527    t *= 15;
01528    cc = (const GLuint *)(code + 8 + t / 8);
01529    kk = cc[0] >> (t & 7);
01530    rgba[BCOMP] = UBYTE_TO_CHAN( UP5(kk) );
01531    rgba[GCOMP] = UBYTE_TO_CHAN( UP5(kk >> 5) );
01532    rgba[RCOMP] = UBYTE_TO_CHAN( UP5(kk >> 10) );
01533    rgba[ACOMP] = CHAN_MAX;
01534 }
01535 
01536 
01537 static void
01538 fxt1_decode_1MIXED (const GLubyte *code, GLint t, GLchan *rgba)
01539 {
01540    const GLuint *cc;
01541    GLuint col[2][3];
01542    GLint glsb, selb;
01543 
01544    cc = (const GLuint *)code;
01545    if (t & 16) {
01546       t &= 15;
01547       t = (cc[1] >> (t * 2)) & 3;
01548       /* col 2 */
01549       col[0][BCOMP] = (*(const GLuint *)(code + 11)) >> 6;
01550       col[0][GCOMP] = CC_SEL(cc, 99);
01551       col[0][RCOMP] = CC_SEL(cc, 104);
01552       /* col 3 */
01553       col[1][BCOMP] = CC_SEL(cc, 109);
01554       col[1][GCOMP] = CC_SEL(cc, 114);
01555       col[1][RCOMP] = CC_SEL(cc, 119);
01556       glsb = CC_SEL(cc, 126);
01557       selb = CC_SEL(cc, 33);
01558    } else {
01559       t = (cc[0] >> (t * 2)) & 3;
01560       /* col 0 */
01561       col[0][BCOMP] = CC_SEL(cc, 64);
01562       col[0][GCOMP] = CC_SEL(cc, 69);
01563       col[0][RCOMP] = CC_SEL(cc, 74);
01564       /* col 1 */
01565       col[1][BCOMP] = CC_SEL(cc, 79);
01566       col[1][GCOMP] = CC_SEL(cc, 84);
01567       col[1][RCOMP] = CC_SEL(cc, 89);
01568       glsb = CC_SEL(cc, 125);
01569       selb = CC_SEL(cc, 1);
01570    }
01571 
01572    if (CC_SEL(cc, 124) & 1) {
01573       /* alpha[0] == 1 */
01574 
01575       if (t == 3) {
01576          /* zero */
01577          rgba[RCOMP] = rgba[BCOMP] = rgba[GCOMP] = rgba[ACOMP] = 0;
01578       } else {
01579          GLubyte r, g, b;
01580          if (t == 0) {
01581             b = UP5(col[0][BCOMP]);
01582             g = UP5(col[0][GCOMP]);
01583             r = UP5(col[0][RCOMP]);
01584          } else if (t == 2) {
01585             b = UP5(col[1][BCOMP]);
01586             g = UP6(col[1][GCOMP], glsb);
01587             r = UP5(col[1][RCOMP]);
01588          } else {
01589             b = (UP5(col[0][BCOMP]) + UP5(col[1][BCOMP])) / 2;
01590             g = (UP5(col[0][GCOMP]) + UP6(col[1][GCOMP], glsb)) / 2;
01591             r = (UP5(col[0][RCOMP]) + UP5(col[1][RCOMP])) / 2;
01592          }
01593          rgba[RCOMP] = UBYTE_TO_CHAN(r);
01594          rgba[GCOMP] = UBYTE_TO_CHAN(g);
01595          rgba[BCOMP] = UBYTE_TO_CHAN(b);
01596          rgba[ACOMP] = CHAN_MAX;
01597       }
01598    } else {
01599       /* alpha[0] == 0 */
01600       GLubyte r, g, b;
01601       if (t == 0) {
01602          b = UP5(col[0][BCOMP]);
01603          g = UP6(col[0][GCOMP], glsb ^ selb);
01604          r = UP5(col[0][RCOMP]);
01605       } else if (t == 3) {
01606          b = UP5(col[1][BCOMP]);
01607          g = UP6(col[1][GCOMP], glsb);
01608          r = UP5(col[1][RCOMP]);
01609       } else {
01610          b = LERP(3, t, UP5(col[0][BCOMP]), UP5(col[1][BCOMP]));
01611          g = LERP(3, t, UP6(col[0][GCOMP], glsb ^ selb),
01612                         UP6(col[1][GCOMP], glsb));
01613          r = LERP(3, t, UP5(col[0][RCOMP]), UP5(col[1][RCOMP]));
01614       }
01615       rgba[RCOMP] = UBYTE_TO_CHAN(r);
01616       rgba[GCOMP] = UBYTE_TO_CHAN(g);
01617       rgba[BCOMP] = UBYTE_TO_CHAN(b);
01618       rgba[ACOMP] = CHAN_MAX;
01619    }
01620 }
01621 
01622 
01623 static void
01624 fxt1_decode_1ALPHA (const GLubyte *code, GLint t, GLchan *rgba)
01625 {
01626    const GLuint *cc;
01627    GLubyte r, g, b, a;
01628 
01629    cc = (const GLuint *)code;
01630    if (CC_SEL(cc, 124) & 1) {
01631       /* lerp == 1 */
01632       GLuint col0[4];
01633 
01634       if (t & 16) {
01635          t &= 15;
01636          t = (cc[1] >> (t * 2)) & 3;
01637          /* col 2 */
01638          col0[BCOMP] = (*(const GLuint *)(code + 11)) >> 6;
01639          col0[GCOMP] = CC_SEL(cc, 99);
01640          col0[RCOMP] = CC_SEL(cc, 104);
01641          col0[ACOMP] = CC_SEL(cc, 119);
01642       } else {
01643          t = (cc[0] >> (t * 2)) & 3;
01644          /* col 0 */
01645          col0[BCOMP] = CC_SEL(cc, 64);
01646          col0[GCOMP] = CC_SEL(cc, 69);
01647          col0[RCOMP] = CC_SEL(cc, 74);
01648          col0[ACOMP] = CC_SEL(cc, 109);
01649       }
01650 
01651       if (t == 0) {
01652          b = UP5(col0[BCOMP]);
01653          g = UP5(col0[GCOMP]);
01654          r = UP5(col0[RCOMP]);
01655          a = UP5(col0[ACOMP]);
01656       } else if (t == 3) {
01657          b = UP5(CC_SEL(cc, 79));
01658          g = UP5(CC_SEL(cc, 84));
01659          r = UP5(CC_SEL(cc, 89));
01660          a = UP5(CC_SEL(cc, 114));
01661       } else {
01662          b = LERP(3, t, UP5(col0[BCOMP]), UP5(CC_SEL(cc, 79)));
01663          g = LERP(3, t, UP5(col0[GCOMP]), UP5(CC_SEL(cc, 84)));
01664          r = LERP(3, t, UP5(col0[RCOMP]), UP5(CC_SEL(cc, 89)));
01665          a = LERP(3, t, UP5(col0[ACOMP]), UP5(CC_SEL(cc, 114)));
01666       }
01667    } else {
01668       /* lerp == 0 */
01669 
01670       if (t & 16) {
01671          cc++;
01672          t &= 15;
01673       }
01674       t = (cc[0] >> (t * 2)) & 3;
01675 
01676       if (t == 3) {
01677          /* zero */
01678          r = g = b = a = 0;
01679       } else {
01680          GLuint kk;
01681          cc = (const GLuint *)code;
01682          a = UP5(cc[3] >> (t * 5 + 13));
01683          t *= 15;
01684          cc = (const GLuint *)(code + 8 + t / 8);
01685          kk = cc[0] >> (t & 7);
01686          b = UP5(kk);
01687          g = UP5(kk >> 5);
01688          r = UP5(kk >> 10);
01689       }
01690    }
01691    rgba[RCOMP] = UBYTE_TO_CHAN(r);
01692    rgba[GCOMP] = UBYTE_TO_CHAN(g);
01693    rgba[BCOMP] = UBYTE_TO_CHAN(b);
01694    rgba[ACOMP] = UBYTE_TO_CHAN(a);
01695 }
01696 
01697 
01698 void
01699 fxt1_decode_1 (const void *texture, GLint stride, /* in pixels */
01700                GLint i, GLint j, GLchan *rgba)
01701 {
01702    static void (*decode_1[]) (const GLubyte *, GLint, GLchan *) = {
01703       fxt1_decode_1HI,     /* cc-high   = "00?" */
01704       fxt1_decode_1HI,     /* cc-high   = "00?" */
01705       fxt1_decode_1CHROMA, /* cc-chroma = "010" */
01706       fxt1_decode_1ALPHA,  /* alpha     = "011" */
01707       fxt1_decode_1MIXED,  /* mixed     = "1??" */
01708       fxt1_decode_1MIXED,  /* mixed     = "1??" */
01709       fxt1_decode_1MIXED,  /* mixed     = "1??" */
01710       fxt1_decode_1MIXED   /* mixed     = "1??" */
01711    };
01712 
01713    const GLubyte *code = (const GLubyte *)texture +
01714                          ((j / 4) * (stride / 8) + (i / 8)) * 16;
01715    GLint mode = CC_SEL(code, 125);
01716    GLint t = i & 7;
01717 
01718    if (t & 4) {
01719       t += 12;
01720    }
01721    t += (j & 3) * 4;
01722 
01723    decode_1[mode](code, t, rgba);
01724 }

Generated on Sun May 27 2012 04:20:29 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.