Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentexcompress_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
1.7.6.1
|