📄 texcompress_fxt1.c
字号:
/*
* Mesa 3-D graphics library
* Version: 6.1
*
* Copyright (C) 1999-2004 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 GLint
fxt1_encode (GLuint width, GLuint height, GLint comps,
const void *source, GLint srcRowStride,
void *dest, GLint destRowStride);
void
fxt1_decode_1 (const void *texture, GLint stride,
GLint i, GLint j, GLubyte *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 GLboolean
texstore_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 GLboolean
texstore_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 void
fetch_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 void
fetch_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 void
fetch_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 void
fetch_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, /* 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, /* 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 1
typedef 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 0
typedef 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 GLint
fxt1_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 GLint
fxt1_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 GLint
fxt1_variance (GLdouble variance[MAX_COMP],
GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -