📄 texcompress_fxt1.c
字号:
/* * Mesa 3-D graphics library * Version: 6.5 * * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *//** * \file texcompress_fxt1.c * GL_EXT_texture_compression_fxt1 support. */#include "glheader.h"#include "imports.h"#include "colormac.h"#include "context.h"#include "convolve.h"#include "image.h"#include "texcompress.h"#include "texformat.h"#include "texstore.h"static voidfxt1_encode (GLuint width, GLuint height, GLint comps, const void *source, GLint srcRowStride, void *dest, GLint destRowStride);voidfxt1_decode_1 (const void *texture, GLint stride, GLint i, GLint j, GLchan *rgba);/** * Called during context initialization. */void_mesa_init_texture_fxt1( GLcontext *ctx ){ (void) ctx;}/** * Called via TexFormat->StoreImage to store an RGB_FXT1 texture. */static GLbooleantexstore_rgb_fxt1(STORE_PARAMS){ const GLchan *pixels; GLint srcRowStride; GLubyte *dst; const GLint texWidth = dstRowStride * 8 / 16; /* a bit of a hack */ const GLchan *tempImage = NULL; ASSERT(dstFormat == &_mesa_texformat_rgb_fxt1); ASSERT(dstXoffset % 8 == 0); ASSERT(dstYoffset % 4 == 0); ASSERT(dstZoffset == 0); (void) dstZoffset; (void) dstImageStride; if (srcFormat != GL_RGB || srcType != CHAN_TYPE || ctx->_ImageTransferState || srcPacking->SwapBytes) { /* convert image to RGB/GLchan */ tempImage = _mesa_make_temp_chan_image(ctx, dims, baseInternalFormat, dstFormat->BaseFormat, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); if (!tempImage) return GL_FALSE; /* out of memory */ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); pixels = tempImage; srcRowStride = 3 * srcWidth; srcFormat = GL_RGB; } else { pixels = (const GLchan *) srcAddr; srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType) / sizeof(GLchan); } dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0, GL_COMPRESSED_RGB_FXT1_3DFX, texWidth, (GLubyte *) dstAddr); fxt1_encode(srcWidth, srcHeight, 3, pixels, srcRowStride, dst, dstRowStride); if (tempImage) _mesa_free((void*) tempImage); return GL_TRUE;}/** * Called via TexFormat->StoreImage to store an RGBA_FXT1 texture. */static GLbooleantexstore_rgba_fxt1(STORE_PARAMS){ const GLchan *pixels; GLint srcRowStride; GLubyte *dst; GLint texWidth = dstRowStride * 8 / 16; /* a bit of a hack */ const GLchan *tempImage = NULL; ASSERT(dstFormat == &_mesa_texformat_rgba_fxt1); ASSERT(dstXoffset % 8 == 0); ASSERT(dstYoffset % 4 == 0); ASSERT(dstZoffset == 0); (void) dstZoffset; (void) dstImageStride; if (srcFormat != GL_RGBA || srcType != CHAN_TYPE || ctx->_ImageTransferState || srcPacking->SwapBytes) { /* convert image to RGBA/GLchan */ tempImage = _mesa_make_temp_chan_image(ctx, dims, baseInternalFormat, dstFormat->BaseFormat, srcWidth, srcHeight, srcDepth, srcFormat, srcType, srcAddr, srcPacking); if (!tempImage) return GL_FALSE; /* out of memory */ _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); pixels = tempImage; srcRowStride = 4 * srcWidth; srcFormat = GL_RGBA; } else { pixels = (const GLchan *) srcAddr; srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType) / sizeof(GLchan); } dst = _mesa_compressed_image_address(dstXoffset, dstYoffset, 0, GL_COMPRESSED_RGBA_FXT1_3DFX, texWidth, (GLubyte *) dstAddr); fxt1_encode(srcWidth, srcHeight, 4, pixels, srcRowStride, dst, dstRowStride); if (tempImage) _mesa_free((void*) tempImage); return GL_TRUE;}static voidfetch_texel_2d_rgba_fxt1( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLchan *texel ){ (void) k; fxt1_decode_1(texImage->Data, texImage->RowStride, i, j, texel);}static voidfetch_texel_2d_f_rgba_fxt1( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel ){ /* just sample as GLchan and convert to float here */ GLchan rgba[4]; (void) k; fxt1_decode_1(texImage->Data, texImage->RowStride, i, j, rgba); texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]); texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]); texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]); texel[ACOMP] = CHAN_TO_FLOAT(rgba[ACOMP]);}static voidfetch_texel_2d_rgb_fxt1( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLchan *texel ){ (void) k; fxt1_decode_1(texImage->Data, texImage->RowStride, i, j, texel); texel[ACOMP] = 255;}static voidfetch_texel_2d_f_rgb_fxt1( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel ){ /* just sample as GLchan and convert to float here */ GLchan rgba[4]; (void) k; fxt1_decode_1(texImage->Data, texImage->RowStride, i, j, rgba); texel[RCOMP] = CHAN_TO_FLOAT(rgba[RCOMP]); texel[GCOMP] = CHAN_TO_FLOAT(rgba[GCOMP]); texel[BCOMP] = CHAN_TO_FLOAT(rgba[BCOMP]); texel[ACOMP] = 1.0F;}const struct gl_texture_format _mesa_texformat_rgb_fxt1 = { MESA_FORMAT_RGB_FXT1, /* MesaFormat */ GL_RGB, /* BaseFormat */ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ 4, /*approx*/ /* RedBits */ 4, /*approx*/ /* GreenBits */ 4, /*approx*/ /* BlueBits */ 0, /* AlphaBits */ 0, /* LuminanceBits */ 0, /* IntensityBits */ 0, /* IndexBits */ 0, /* DepthBits */ 0, /* StencilBits */ 0, /* TexelBytes */ texstore_rgb_fxt1, /* StoreTexImageFunc */ NULL, /*impossible*/ /* FetchTexel1D */ fetch_texel_2d_rgb_fxt1, /* FetchTexel2D */ NULL, /*impossible*/ /* FetchTexel3D */ NULL, /*impossible*/ /* FetchTexel1Df */ fetch_texel_2d_f_rgb_fxt1, /* FetchTexel2Df */ NULL, /*impossible*/ /* FetchTexel3Df */};const struct gl_texture_format _mesa_texformat_rgba_fxt1 = { MESA_FORMAT_RGBA_FXT1, /* MesaFormat */ GL_RGBA, /* BaseFormat */ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ 4, /*approx*/ /* RedBits */ 4, /*approx*/ /* GreenBits */ 4, /*approx*/ /* BlueBits */ 1, /*approx*/ /* AlphaBits */ 0, /* LuminanceBits */ 0, /* IntensityBits */ 0, /* IndexBits */ 0, /* DepthBits */ 0, /* StencilBits */ 0, /* TexelBytes */ texstore_rgba_fxt1, /* StoreTexImageFunc */ NULL, /*impossible*/ /* FetchTexel1D */ fetch_texel_2d_rgba_fxt1, /* FetchTexel2D */ NULL, /*impossible*/ /* FetchTexel3D */ NULL, /*impossible*/ /* FetchTexel1Df */ fetch_texel_2d_f_rgba_fxt1, /* FetchTexel2Df */ NULL, /*impossible*/ /* FetchTexel3Df */};/***************************************************************************\ * FXT1 encoder * * The encoder was built by reversing the decoder, * and is vaguely based on Texus2 by 3dfx. Note that this code * is merely a proof of concept, since it is highly UNoptimized; * moreover, it is sub-optimal due to initial conditions passed * to Lloyd's algorithm (the interpolation modes are even worse).\***************************************************************************/#define MAX_COMP 4 /* ever needed maximum number of components in texel */#define MAX_VECT 4 /* ever needed maximum number of base vectors to find */#define N_TEXELS 32 /* number of texels in a block (always 32) */#define LL_N_REP 50 /* number of iterations in lloyd's vq */#define LL_RMS_D 10 /* fault tolerance (maximum delta) */#define LL_RMS_E 255 /* fault tolerance (maximum error) */#define ALPHA_TS 2 /* alpha threshold: (255 - ALPHA_TS) deemed opaque */#define ISTBLACK(v) (*((GLuint *)(v)) == 0)/* * Define a 64-bit unsigned integer type and macros */#if defined(__GNUC__) && !defined(__cplusplus)#define FX64_NATIVE 1typedef unsigned long long Fx64;#define FX64_MOV32(a, b) a = b#define FX64_OR32(a, b) a |= b#define FX64_SHL(a, c) a <<= c#else /* !__GNUC__ */#define FX64_NATIVE 0typedef struct { GLuint lo, hi;} Fx64;#define FX64_MOV32(a, b) a.lo = b#define FX64_OR32(a, b) a.lo |= b#define FX64_SHL(a, c) \ do { \ if ((c) >= 32) { \ a.hi = a.lo << ((c) - 32); \ a.lo = 0; \ } else { \ a.hi = (a.hi << (c)) | (a.lo >> (32 - (c))); \ a.lo <<= (c); \ } \ } while (0)#endif /* !__GNUC__ */#define F(i) (GLfloat)1 /* can be used to obtain an oblong metric: 0.30 / 0.59 / 0.11 */#define SAFECDOT 1 /* for paranoids */#define MAKEIVEC(NV, NC, IV, B, V0, V1) \ do { \ /* compute interpolation vector */ \ GLfloat d2 = 0.0F; \ GLfloat rd2; \ \ for (i = 0; i < NC; i++) { \ IV[i] = (V1[i] - V0[i]) * F(i); \ d2 += IV[i] * IV[i]; \ } \ rd2 = (GLfloat)NV / d2; \ B = 0; \ for (i = 0; i < NC; i++) { \ IV[i] *= F(i); \ B -= IV[i] * V0[i]; \ IV[i] *= rd2; \ } \ B = B * rd2 + 0.5f; \ } while (0)#define CALCCDOT(TEXEL, NV, NC, IV, B, V)\ do { \ GLfloat dot = 0.0F; \ for (i = 0; i < NC; i++) { \ dot += V[i] * IV[i]; \ } \ TEXEL = (GLint)(dot + B); \ if (SAFECDOT) { \ if (TEXEL < 0) { \ TEXEL = 0; \ } else if (TEXEL > NV) { \ TEXEL = NV; \ } \ } \ } while (0)static GLintfxt1_bestcol (GLfloat vec[][MAX_COMP], GLint nv, GLubyte input[MAX_COMP], GLint nc){ GLint i, j, best = -1; GLfloat err = 1e9; /* big enough */ for (j = 0; j < nv; j++) { GLfloat e = 0.0F; for (i = 0; i < nc; i++) { e += (vec[j][i] - input[i]) * (vec[j][i] - input[i]); } if (e < err) { err = e; best = j; } } return best;}static GLintfxt1_worst (GLfloat vec[MAX_COMP], GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n){ GLint i, k, worst = -1; GLfloat err = -1.0F; /* small enough */ for (k = 0; k < n; k++) { GLfloat e = 0.0F; for (i = 0; i < nc; i++) { e += (vec[i] - input[k][i]) * (vec[i] - input[k][i]); } if (e > err) { err = e; worst = k; } } return worst;}static GLintfxt1_variance (GLdouble variance[MAX_COMP], GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n){ GLint i, k, best = 0; GLint sx, sx2; GLdouble var, maxvar = -1; /* small enough */ GLdouble teenth = 1.0 / n; for (i = 0; i < nc; i++) { sx = sx2 = 0; for (k = 0; k < n; k++) { GLint t = input[k][i]; sx += t;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -