130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o/* 230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * Mesa 3-D graphics library 3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * Version: 7.1 430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * 530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * 7543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * Permission is hereby granted, free of charge, to any person obtaining a 8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * copy of this software and associated documentation files (the "Software"), 930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * to deal in the Software without restriction, including without limitation 1030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * and/or sell copies of the Software, and to permit persons to whom the 1230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * Software is furnished to do so, subject to the following conditions: 1330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * 1430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * The above copyright notice and this permission notice shall be included 1530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * in all copies or substantial portions of the Software. 1630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * 1730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 2130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 2230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o */ 2430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 2531dbecd482405e0d3a67eb58e1a1c8cb9f2ad83eTheodore Ts'o 2630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o/** 2730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * \file texcompress_fxt1.c 28819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o * GL_3DFX_texture_compression_FXT1 support. 29e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 30e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 3130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 3230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#include "glheader.h" 3330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#include "imports.h" 340f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o#include "colormac.h" 350f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o#include "image.h" 36a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o#include "macros.h" 37a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o#include "mfeatures.h" 38a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o#include "mipmap.h" 3930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#include "texcompress.h" 4030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#include "texcompress_fxt1.h" 4130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#include "texstore.h" 4230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#include "swrast/s_context.h" 4330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 4430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 4530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#if FEATURE_texture_fxt1 4630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 4730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 4830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'ostatic void 4930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'ofxt1_encode (GLuint width, GLuint height, GLint comps, 5030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o const void *source, GLint srcRowStride, 51c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o void *dest, GLint destRowStride); 527b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o 537b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'ovoid 54efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ofxt1_decode_1 (const void *texture, GLint stride, 5530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o GLint i, GLint j, GLubyte *rgba); 5630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 5730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 5830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o/** 5930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * Store user's image in rgb_fxt1 format. 6030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o */ 61a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'oGLboolean 62a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o_mesa_texstore_rgb_fxt1(TEXSTORE_PARAMS) 63a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o{ 64a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o const GLubyte *pixels; 65a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o GLint srcRowStride; 66a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o GLubyte *dst; 67a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o const GLubyte *tempImage = NULL; 68efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 69ee01079a17bfecd17292ccd60058056fb3a8ba6cTheodore Ts'o ASSERT(dstFormat == MESA_FORMAT_RGB_FXT1); 707b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o 7130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (srcFormat != GL_RGB || 7230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o srcType != GL_UNSIGNED_BYTE || 7330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o ctx->_ImageTransferState || 7430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o srcPacking->RowLength != srcWidth || 75efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o srcPacking->SwapBytes) { 7630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o /* convert image to RGB/GLubyte */ 7730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o tempImage = _mesa_make_temp_ubyte_image(ctx, dims, 78c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o baseInternalFormat, 79c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o _mesa_get_format_base_format(dstFormat), 8030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o srcWidth, srcHeight, srcDepth, 8130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o srcFormat, srcType, srcAddr, 8230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o srcPacking); 83a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o if (!tempImage) 84a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o return GL_FALSE; /* out of memory */ 85a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o pixels = tempImage; 86a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o srcRowStride = 3 * srcWidth; 87a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o srcFormat = GL_RGB; 88a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o } 8930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o else { 9079a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight, 9179a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o srcFormat, srcType, 0, 0); 9279a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o 9379a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, 9479a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o srcType) / sizeof(GLubyte); 9579a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o } 9679a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o 9779a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o dst = dstSlices[0]; 9879a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o 9979a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o fxt1_encode(srcWidth, srcHeight, 3, pixels, srcRowStride, 100e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dst, dstRowStride); 101e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 102e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (tempImage) 103e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free((void*) tempImage); 104e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return GL_TRUE; 106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/** 110e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Store user's image in rgba_fxt1 format. 111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP AbgrallGLboolean 113e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall_mesa_texstore_rgba_fxt1(TEXSTORE_PARAMS) 114e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 115e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const GLubyte *pixels; 116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall GLint srcRowStride; 117e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall GLubyte *dst; 11830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o const GLubyte *tempImage = NULL; 11930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 12030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o ASSERT(dstFormat == MESA_FORMAT_RGBA_FXT1); 121f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o 12230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (srcFormat != GL_RGBA || 12330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o srcType != GL_UNSIGNED_BYTE || 1240f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o ctx->_ImageTransferState || 125efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o srcPacking->SwapBytes) { 12630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o /* convert image to RGBA/GLubyte */ 1270f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o tempImage = _mesa_make_temp_ubyte_image(ctx, dims, 12830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o baseInternalFormat, 12930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o _mesa_get_format_base_format(dstFormat), 13030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o srcWidth, srcHeight, srcDepth, 13130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o srcFormat, srcType, srcAddr, 13230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o srcPacking); 13330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (!tempImage) 13430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o return GL_FALSE; /* out of memory */ 13530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o pixels = tempImage; 13630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o srcRowStride = 4 * srcWidth; 13730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o srcFormat = GL_RGBA; 138e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 139a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o else { 140e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall pixels = _mesa_image_address2d(srcPacking, srcAddr, srcWidth, srcHeight, 14130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o srcFormat, srcType, 0, 0); 14230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 14330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, 14430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o srcType) / sizeof(GLubyte); 145e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 14630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 14730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o dst = dstSlices[0]; 14830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 14930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o fxt1_encode(srcWidth, srcHeight, 4, pixels, srcRowStride, 15030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o dst, dstRowStride); 15130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 15230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (tempImage) 15330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o free((void*) tempImage); 1540f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 1550f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o return GL_TRUE; 1560f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o} 1570f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 1580f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 1590f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'ovoid 160e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall_mesa_fetch_texel_2d_f_rgba_fxt1( const struct swrast_texture_image *texImage, 1610f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o GLint i, GLint j, GLint k, GLfloat *texel ) 1620f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o{ 1630f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o /* just sample as GLubyte and convert to float here */ 1640f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o GLubyte rgba[4]; 1650f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o (void) k; 1660f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o fxt1_decode_1(texImage->Map, texImage->RowStride, i, j, rgba); 1670f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o texel[RCOMP] = UBYTE_TO_FLOAT(rgba[RCOMP]); 1680f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o texel[GCOMP] = UBYTE_TO_FLOAT(rgba[GCOMP]); 1690f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o texel[BCOMP] = UBYTE_TO_FLOAT(rgba[BCOMP]); 1700f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o texel[ACOMP] = UBYTE_TO_FLOAT(rgba[ACOMP]); 1710f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o} 1720f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 1730f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 1740f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'ovoid 1750f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o_mesa_fetch_texel_2d_f_rgb_fxt1( const struct swrast_texture_image *texImage, 1760f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o GLint i, GLint j, GLint k, GLfloat *texel ) 1770f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o{ 1780f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o /* just sample as GLubyte and convert to float here */ 1790f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o GLubyte rgba[4]; 1800f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o (void) k; 1810f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o fxt1_decode_1(texImage->Map, texImage->RowStride, i, j, rgba); 1820f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o texel[RCOMP] = UBYTE_TO_FLOAT(rgba[RCOMP]); 1830f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o texel[GCOMP] = UBYTE_TO_FLOAT(rgba[GCOMP]); 1840f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o texel[BCOMP] = UBYTE_TO_FLOAT(rgba[BCOMP]); 1850f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o texel[ACOMP] = 1.0F; 1860f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o} 1870f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 1880f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 189e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 190e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/***************************************************************************\ 1910f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o * FXT1 encoder 1920f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o * 1930f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o * The encoder was built by reversing the decoder, 1940f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o * and is vaguely based on Texus2 by 3dfx. Note that this code 1950f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o * is merely a proof of concept, since it is highly UNoptimized; 196e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * moreover, it is sub-optimal due to initial conditions passed 197e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * to Lloyd's algorithm (the interpolation modes are even worse). 198e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall\***************************************************************************/ 1990f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 2000f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 2010f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o#define MAX_COMP 4 /* ever needed maximum number of components in texel */ 2020f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o#define MAX_VECT 4 /* ever needed maximum number of base vectors to find */ 2030f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o#define N_TEXELS 32 /* number of texels in a block (always 32) */ 2040f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o#define LL_N_REP 50 /* number of iterations in lloyd's vq */ 2050f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o#define LL_RMS_D 10 /* fault tolerance (maximum delta) */ 2060f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o#define LL_RMS_E 255 /* fault tolerance (maximum error) */ 2070f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o#define ALPHA_TS 2 /* alpha threshold: (255 - ALPHA_TS) deemed opaque */ 208efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o#define ISTBLACK(v) (*((GLuint *)(v)) == 0) 2090f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 21030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 21130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o/* 21230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o * Define a 64-bit unsigned integer type and macros 213efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o */ 21430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#if 1 21530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 21630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define FX64_NATIVE 1 217efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 21830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'otypedef uint64_t Fx64; 219c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o 220c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o#define FX64_MOV32(a, b) a = b 22130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define FX64_OR32(a, b) a |= b 22230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define FX64_SHL(a, c) a <<= c 22330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 22430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#else 22530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 22630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define FX64_NATIVE 0 22779a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o 22830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'otypedef struct { 22930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o GLuint lo, hi; 2300f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o} Fx64; 231819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o 232819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o#define FX64_MOV32(a, b) a.lo = b 233b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#define FX64_OR32(a, b) a.lo |= b 23430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 23530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o#define FX64_SHL(a, c) \ 23630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o do { \ 23730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if ((c) >= 32) { \ 238819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o a.hi = a.lo << ((c) - 32); \ 2390f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o a.lo = 0; \ 24030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } else { \ 24130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o a.hi = (a.hi << (c)) | (a.lo >> (32 - (c))); \ 2420f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o a.lo <<= (c); \ 24330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } \ 24430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } while (0) 2450f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 2460f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o#endif 2470f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 2480f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 2490f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o#define F(i) (GLfloat)1 /* can be used to obtain an oblong metric: 0.30 / 0.59 / 0.11 */ 250819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o#define SAFECDOT 1 /* for paranoids */ 2510f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 2520f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o#define MAKEIVEC(NV, NC, IV, B, V0, V1) \ 253efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o do { \ 2540f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o /* compute interpolation vector */ \ 2550f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o GLfloat d2 = 0.0F; \ 2560f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o GLfloat rd2; \ 2570f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o \ 2580f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o for (i = 0; i < NC; i++) { \ 25930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o IV[i] = (V1[i] - V0[i]) * F(i); \ 260efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o d2 += IV[i] * IV[i]; \ 2610f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o } \ 26230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o rd2 = (GLfloat)NV / d2; \ 26330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o B = 0; \ 26430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o for (i = 0; i < NC; i++) { \ 26530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o IV[i] *= F(i); \ 26630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o B -= IV[i] * V0[i]; \ 26730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o IV[i] *= rd2; \ 268f12e285ffd9ff0b37c4f91d5ab2b021ed1eb43beTheodore Ts'o } \ 26979a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o B = B * rd2 + 0.5f; \ 27030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } while (0) 27130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 2720f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o#define CALCCDOT(TEXEL, NV, NC, IV, B, V)\ 2730f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o do { \ 274546a1ff18cc912003883ff67ba3e87c69f700fc4Theodore Ts'o GLfloat dot = 0.0F; \ 27530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o for (i = 0; i < NC; i++) { \ 27630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o dot += V[i] * IV[i]; \ 27730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } \ 27830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o TEXEL = (GLint)(dot + B); \ 27930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (SAFECDOT) { \ 2801f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o if (TEXEL < 0) { \ 28130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o TEXEL = 0; \ 2820f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o } else if (TEXEL > NV) { \ 2830f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o TEXEL = NV; \ 28430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } \ 28530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } \ 286efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o } while (0) 2870f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 2880f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 2890f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'ostatic GLint 2900f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'ofxt1_bestcol (GLfloat vec[][MAX_COMP], GLint nv, 2910f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o GLubyte input[MAX_COMP], GLint nc) 2920f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o{ 2930f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o GLint i, j, best = -1; 2940f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o GLfloat err = 1e9; /* big enough */ 2950f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 2960f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o for (j = 0; j < nv; j++) { 29730fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o GLfloat e = 0.0F; 29830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o for (i = 0; i < nc; i++) { 2990f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o e += (vec[j][i] - input[i]) * (vec[j][i] - input[i]); 300e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 301e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (e < err) { 302e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = e; 303e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall best = j; 304e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 305e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 306e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 307e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return best; 308e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 309e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 310e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 311e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic GLint 312e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallfxt1_worst (GLfloat vec[MAX_COMP], 313e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n) 3140f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o{ 3150f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o GLint i, k, worst = -1; 3160f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o GLfloat err = -1.0F; /* small enough */ 3170f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o 3180f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o for (k = 0; k < n; k++) { 3190f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o GLfloat e = 0.0F; 32030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o for (i = 0; i < nc; i++) { 321efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o e += (vec[i] - input[k][i]) * (vec[i] - input[k][i]); 3220f6794591edf238825f8ab80c885e83d1efbf203Theodore Ts'o } 323e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (e > err) { 324e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = e; 325e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall worst = k; 326e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 327e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 328e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 329e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return worst; 330e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 331e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 33230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 33330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'ostatic GLint 33430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'ofxt1_variance (GLdouble variance[MAX_COMP], 33530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n) 33630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o{ 337819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o GLint i, k, best = 0; 338819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o GLint sx, sx2; 33930fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o GLdouble var, maxvar = -1; /* small enough */ 34030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o GLdouble teenth = 1.0 / n; 34130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o 34230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o for (i = 0; i < nc; i++) { 34330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o sx = sx2 = 0; 34430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o for (k = 0; k < n; k++) { 34530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o GLint t = input[k][i]; 34630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o sx += t; 347819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o sx2 += t * t; 34830fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 3491f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o var = sx2 * teenth - sx * sx * teenth * teenth; 35030fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (maxvar < var) { 35130fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o maxvar = var; 35230fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o best = i; 35330fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 35430fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o if (variance) { 35530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o variance[i] = var; 35630fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o } 357819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o } 358819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o 359819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o return best; 360819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o} 361819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o 362efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 363819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'ostatic GLint 364819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'ofxt1_choose (GLfloat vec[][MAX_COMP], GLint nv, 36520754488a228fed766126a2788bce523154a48f0Theodore Ts'o GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n) 36620754488a228fed766126a2788bce523154a48f0Theodore Ts'o{ 367819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o#if 0 368819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o /* Choose colors from a grid. 369819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o */ 370819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o GLint i, j; 37179a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o 37279a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o for (j = 0; j < nv; j++) { 37379a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o GLint m = j * (n - 1) / (nv - 1); 374819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o for (i = 0; i < nc; i++) { 37579a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o vec[j][i] = input[m][i]; 37679a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o } 377819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o } 378819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o#else 379819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o /* Our solution here is to find the darkest and brightest colors in 380819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o * the 8x4 tile and use those as the two representative colors. 381819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o * There are probably better algorithms to use (histogram-based). 382819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o */ 383819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o GLint i, j, k; 384819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o GLint minSum = 2000; /* big enough */ 385819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o GLint maxSum = -1; /* small enough */ 386819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o GLint minCol = 0; /* phoudoin: silent compiler! */ 387819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o GLint maxCol = 0; /* phoudoin: silent compiler! */ 388819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o 389819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o struct { 390819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o GLint flag; 391819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o GLint key; 39279a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o GLint freq; 393819157db798cd514aa2f3ae421d64e2e0c9b7fa8Theodore Ts'o GLint idx; 39479a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o } hist[N_TEXELS]; 39530fab293065b7fc6d7d138e8e9eea533a3560873Theodore Ts'o GLint lenh = 0; 396e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 397e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(hist, 0, sizeof(hist)); 398e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 399e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (k = 0; k < n; k++) { 400e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall GLint l; 401e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall GLint key = 0; 402e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall GLint sum = 0; 403e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < nc; i++) { 404e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall key <<= 8; 405e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall key |= input[k][i]; 406e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sum += input[k][i]; 407e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 408e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (l = 0; l < n; l++) { 409e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!hist[l].flag) { 410e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* alloc new slot */ 411e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall hist[l].flag = !0; 412e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall hist[l].key = key; 413e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall hist[l].freq = 1; 414e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall hist[l].idx = k; 415e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall lenh = l + 1; 416e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 417e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else if (hist[l].key == key) { 418e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall hist[l].freq++; 419e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 420e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 421e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 422e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (minSum > sum) { 423e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall minSum = sum; 424e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall minCol = k; 425e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 426e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (maxSum < sum) { 427e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall maxSum = sum; 428e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall maxCol = k; 429e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 430e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 431e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 432e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (lenh <= nv) { 433e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (j = 0; j < lenh; j++) { 434e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < nc; i++) { 435e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall vec[j][i] = (GLfloat)input[hist[j].idx][i]; 436e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 437e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 438e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (; j < nv; j++) { 439e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < nc; i++) { 440e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall vec[j][i] = vec[0][i]; 441e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 442e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 44379a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o return 0; 44479a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o } 445efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 44679a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o for (j = 0; j < nv; j++) { 447e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < nc; i++) { 44879a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o vec[j][i] = ((nv - 1 - j) * input[minCol][i] + j * input[maxCol][i] + (nv - 1) / 2) / (GLfloat)(nv - 1); 449e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 45079a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o } 451e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 452e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 45379a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o return !0; 454efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o} 455e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 456e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 457e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic GLint 458e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallfxt1_lloyd (GLfloat vec[][MAX_COMP], GLint nv, 459e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall GLubyte input[N_TEXELS][MAX_COMP], GLint nc, GLint n) 460e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 461e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Use the generalized lloyd's algorithm for VQ: 462e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * find 4 color vectors. 463e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 464e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * for each sample color 465e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * sort to nearest vector. 466e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 467e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * replace each vector with the centroid of its matching colors. 468e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 469e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * repeat until RMS doesn't improve. 470e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 471e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * if a color vector has no samples, or becomes the same as another 472e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * vector, replace it with the color which is farthest from a sample. 473e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 474e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * vec[][MAX_COMP] initial vectors and resulting colors 475e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * nv number of resulting colors required 476e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * input[N_TEXELS][MAX_COMP] input texels 477e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * nc number of components in input / vec 478a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o * n number of input samples 479a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o */ 480a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o 481a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o GLint sum[MAX_VECT][MAX_COMP]; /* used to accumulate closest texels */ 482a435ec3449694a8fa299337197cc09624960a3a6Theodore Ts'o GLint cnt[MAX_VECT]; /* how many times a certain vector was chosen */ 48379a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o GLfloat error, lasterror = 1e9; 484e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 485e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall GLint i, j, k, rep; 486e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 48727a0e958e619c3ca105e575670416a964fa2678fTheodore Ts'o /* the quantizer */ 488e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (rep = 0; rep < LL_N_REP; rep++) { 489e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* reset sums & counters */ 490e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (j = 0; j < nv; j++) { 491e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < nc; i++) { 492e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sum[j][i] = 0; 493e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 494e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall cnt[j] = 0; 495e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 496e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall error = 0; 497e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 49879a90bdad033e101c38bb3c3207c8f4be47a2de7Theodore Ts'o /* scan whole block */ 499 for (k = 0; k < n; k++) { 500#if 1 501 GLint best = -1; 502 GLfloat err = 1e9; /* big enough */ 503 /* determine best vector */ 504 for (j = 0; j < nv; j++) { 505 GLfloat e = (vec[j][0] - input[k][0]) * (vec[j][0] - input[k][0]) + 506 (vec[j][1] - input[k][1]) * (vec[j][1] - input[k][1]) + 507 (vec[j][2] - input[k][2]) * (vec[j][2] - input[k][2]); 508 if (nc == 4) { 509 e += (vec[j][3] - input[k][3]) * (vec[j][3] - input[k][3]); 510 } 511 if (e < err) { 512 err = e; 513 best = j; 514 } 515 } 516#else 517 GLint best = fxt1_bestcol(vec, nv, input[k], nc, &err); 518#endif 519 assert(best >= 0); 520 /* add in closest color */ 521 for (i = 0; i < nc; i++) { 522 sum[best][i] += input[k][i]; 523 } 524 /* mark this vector as used */ 525 cnt[best]++; 526 /* accumulate error */ 527 error += err; 528 } 529 530 /* check RMS */ 531 if ((error < LL_RMS_E) || 532 ((error < lasterror) && ((lasterror - error) < LL_RMS_D))) { 533 return !0; /* good match */ 534 } 535 lasterror = error; 536 537 /* move each vector to the barycenter of its closest colors */ 538 for (j = 0; j < nv; j++) { 539 if (cnt[j]) { 540 GLfloat div = 1.0F / cnt[j]; 541 for (i = 0; i < nc; i++) { 542 vec[j][i] = div * sum[j][i]; 543 } 544 } else { 545 /* this vec has no samples or is identical with a previous vec */ 546 GLint worst = fxt1_worst(vec[j], input, nc, n); 547 for (i = 0; i < nc; i++) { 548 vec[j][i] = input[worst][i]; 549 } 550 } 551 } 552 } 553 554 return 0; /* could not converge fast enough */ 555} 556 557 558static void 559fxt1_quantize_CHROMA (GLuint *cc, 560 GLubyte input[N_TEXELS][MAX_COMP]) 561{ 562 const GLint n_vect = 4; /* 4 base vectors to find */ 563 const GLint n_comp = 3; /* 3 components: R, G, B */ 564 GLfloat vec[MAX_VECT][MAX_COMP]; 565 GLint i, j, k; 566 Fx64 hi; /* high quadword */ 567 GLuint lohi, lolo; /* low quadword: hi dword, lo dword */ 568 569 if (fxt1_choose(vec, n_vect, input, n_comp, N_TEXELS) != 0) { 570 fxt1_lloyd(vec, n_vect, input, n_comp, N_TEXELS); 571 } 572 573 FX64_MOV32(hi, 4); /* cc-chroma = "010" + unused bit */ 574 for (j = n_vect - 1; j >= 0; j--) { 575 for (i = 0; i < n_comp; i++) { 576 /* add in colors */ 577 FX64_SHL(hi, 5); 578 FX64_OR32(hi, (GLuint)(vec[j][i] / 8.0F)); 579 } 580 } 581 ((Fx64 *)cc)[1] = hi; 582 583 lohi = lolo = 0; 584 /* right microtile */ 585 for (k = N_TEXELS - 1; k >= N_TEXELS/2; k--) { 586 lohi <<= 2; 587 lohi |= fxt1_bestcol(vec, n_vect, input[k], n_comp); 588 } 589 /* left microtile */ 590 for (; k >= 0; k--) { 591 lolo <<= 2; 592 lolo |= fxt1_bestcol(vec, n_vect, input[k], n_comp); 593 } 594 cc[1] = lohi; 595 cc[0] = lolo; 596} 597 598 599static void 600fxt1_quantize_ALPHA0 (GLuint *cc, 601 GLubyte input[N_TEXELS][MAX_COMP], 602 GLubyte reord[N_TEXELS][MAX_COMP], GLint n) 603{ 604 const GLint n_vect = 3; /* 3 base vectors to find */ 605 const GLint n_comp = 4; /* 4 components: R, G, B, A */ 606 GLfloat vec[MAX_VECT][MAX_COMP]; 607 GLint i, j, k; 608 Fx64 hi; /* high quadword */ 609 GLuint lohi, lolo; /* low quadword: hi dword, lo dword */ 610 611 /* the last vector indicates zero */ 612 for (i = 0; i < n_comp; i++) { 613 vec[n_vect][i] = 0; 614 } 615 616 /* the first n texels in reord are guaranteed to be non-zero */ 617 if (fxt1_choose(vec, n_vect, reord, n_comp, n) != 0) { 618 fxt1_lloyd(vec, n_vect, reord, n_comp, n); 619 } 620 621 FX64_MOV32(hi, 6); /* alpha = "011" + lerp = 0 */ 622 for (j = n_vect - 1; j >= 0; j--) { 623 /* add in alphas */ 624 FX64_SHL(hi, 5); 625 FX64_OR32(hi, (GLuint)(vec[j][ACOMP] / 8.0F)); 626 } 627 for (j = n_vect - 1; j >= 0; j--) { 628 for (i = 0; i < n_comp - 1; i++) { 629 /* add in colors */ 630 FX64_SHL(hi, 5); 631 FX64_OR32(hi, (GLuint)(vec[j][i] / 8.0F)); 632 } 633 } 634 ((Fx64 *)cc)[1] = hi; 635 636 lohi = lolo = 0; 637 /* right microtile */ 638 for (k = N_TEXELS - 1; k >= N_TEXELS/2; k--) { 639 lohi <<= 2; 640 lohi |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp); 641 } 642 /* left microtile */ 643 for (; k >= 0; k--) { 644 lolo <<= 2; 645 lolo |= fxt1_bestcol(vec, n_vect + 1, input[k], n_comp); 646 } 647 cc[1] = lohi; 648 cc[0] = lolo; 649} 650 651 652static void 653fxt1_quantize_ALPHA1 (GLuint *cc, 654 GLubyte input[N_TEXELS][MAX_COMP]) 655{ 656 const GLint n_vect = 3; /* highest vector number in each microtile */ 657 const GLint n_comp = 4; /* 4 components: R, G, B, A */ 658 GLfloat vec[1 + 1 + 1][MAX_COMP]; /* 1.5 extrema for each sub-block */ 659 GLfloat b, iv[MAX_COMP]; /* interpolation vector */ 660 GLint i, j, k; 661 Fx64 hi; /* high quadword */ 662 GLuint lohi, lolo; /* low quadword: hi dword, lo dword */ 663 664 GLint minSum; 665 GLint maxSum; 666 GLint minColL = 0, maxColL = 0; 667 GLint minColR = 0, maxColR = 0; 668 GLint sumL = 0, sumR = 0; 669 GLint nn_comp; 670 /* Our solution here is to find the darkest and brightest colors in 671 * the 4x4 tile and use those as the two representative colors. 672 * There are probably better algorithms to use (histogram-based). 673 */ 674 nn_comp = n_comp; 675 while ((minColL == maxColL) && nn_comp) { 676 minSum = 2000; /* big enough */ 677 maxSum = -1; /* small enough */ 678 for (k = 0; k < N_TEXELS / 2; k++) { 679 GLint sum = 0; 680 for (i = 0; i < nn_comp; i++) { 681 sum += input[k][i]; 682 } 683 if (minSum > sum) { 684 minSum = sum; 685 minColL = k; 686 } 687 if (maxSum < sum) { 688 maxSum = sum; 689 maxColL = k; 690 } 691 sumL += sum; 692 } 693 694 nn_comp--; 695 } 696 697 nn_comp = n_comp; 698 while ((minColR == maxColR) && nn_comp) { 699 minSum = 2000; /* big enough */ 700 maxSum = -1; /* small enough */ 701 for (k = N_TEXELS / 2; k < N_TEXELS; k++) { 702 GLint sum = 0; 703 for (i = 0; i < nn_comp; i++) { 704 sum += input[k][i]; 705 } 706 if (minSum > sum) { 707 minSum = sum; 708 minColR = k; 709 } 710 if (maxSum < sum) { 711 maxSum = sum; 712 maxColR = k; 713 } 714 sumR += sum; 715 } 716 717 nn_comp--; 718 } 719 720 /* choose the common vector (yuck!) */ 721 { 722 GLint j1, j2; 723 GLint v1 = 0, v2 = 0; 724 GLfloat err = 1e9; /* big enough */ 725 GLfloat tv[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */ 726 for (i = 0; i < n_comp; i++) { 727 tv[0][i] = input[minColL][i]; 728 tv[1][i] = input[maxColL][i]; 729 tv[2][i] = input[minColR][i]; 730 tv[3][i] = input[maxColR][i]; 731 } 732 for (j1 = 0; j1 < 2; j1++) { 733 for (j2 = 2; j2 < 4; j2++) { 734 GLfloat e = 0.0F; 735 for (i = 0; i < n_comp; i++) { 736 e += (tv[j1][i] - tv[j2][i]) * (tv[j1][i] - tv[j2][i]); 737 } 738 if (e < err) { 739 err = e; 740 v1 = j1; 741 v2 = j2; 742 } 743 } 744 } 745 for (i = 0; i < n_comp; i++) { 746 vec[0][i] = tv[1 - v1][i]; 747 vec[1][i] = (tv[v1][i] * sumL + tv[v2][i] * sumR) / (sumL + sumR); 748 vec[2][i] = tv[5 - v2][i]; 749 } 750 } 751 752 /* left microtile */ 753 cc[0] = 0; 754 if (minColL != maxColL) { 755 /* compute interpolation vector */ 756 MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]); 757 758 /* add in texels */ 759 lolo = 0; 760 for (k = N_TEXELS / 2 - 1; k >= 0; k--) { 761 GLint texel; 762 /* interpolate color */ 763 CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); 764 /* add in texel */ 765 lolo <<= 2; 766 lolo |= texel; 767 } 768 769 cc[0] = lolo; 770 } 771 772 /* right microtile */ 773 cc[1] = 0; 774 if (minColR != maxColR) { 775 /* compute interpolation vector */ 776 MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[1]); 777 778 /* add in texels */ 779 lohi = 0; 780 for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) { 781 GLint texel; 782 /* interpolate color */ 783 CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); 784 /* add in texel */ 785 lohi <<= 2; 786 lohi |= texel; 787 } 788 789 cc[1] = lohi; 790 } 791 792 FX64_MOV32(hi, 7); /* alpha = "011" + lerp = 1 */ 793 for (j = n_vect - 1; j >= 0; j--) { 794 /* add in alphas */ 795 FX64_SHL(hi, 5); 796 FX64_OR32(hi, (GLuint)(vec[j][ACOMP] / 8.0F)); 797 } 798 for (j = n_vect - 1; j >= 0; j--) { 799 for (i = 0; i < n_comp - 1; i++) { 800 /* add in colors */ 801 FX64_SHL(hi, 5); 802 FX64_OR32(hi, (GLuint)(vec[j][i] / 8.0F)); 803 } 804 } 805 ((Fx64 *)cc)[1] = hi; 806} 807 808 809static void 810fxt1_quantize_HI (GLuint *cc, 811 GLubyte input[N_TEXELS][MAX_COMP], 812 GLubyte reord[N_TEXELS][MAX_COMP], GLint n) 813{ 814 const GLint n_vect = 6; /* highest vector number */ 815 const GLint n_comp = 3; /* 3 components: R, G, B */ 816 GLfloat b = 0.0F; /* phoudoin: silent compiler! */ 817 GLfloat iv[MAX_COMP]; /* interpolation vector */ 818 GLint i, k; 819 GLuint hihi; /* high quadword: hi dword */ 820 821 GLint minSum = 2000; /* big enough */ 822 GLint maxSum = -1; /* small enough */ 823 GLint minCol = 0; /* phoudoin: silent compiler! */ 824 GLint maxCol = 0; /* phoudoin: silent compiler! */ 825 826 /* Our solution here is to find the darkest and brightest colors in 827 * the 8x4 tile and use those as the two representative colors. 828 * There are probably better algorithms to use (histogram-based). 829 */ 830 for (k = 0; k < n; k++) { 831 GLint sum = 0; 832 for (i = 0; i < n_comp; i++) { 833 sum += reord[k][i]; 834 } 835 if (minSum > sum) { 836 minSum = sum; 837 minCol = k; 838 } 839 if (maxSum < sum) { 840 maxSum = sum; 841 maxCol = k; 842 } 843 } 844 845 hihi = 0; /* cc-hi = "00" */ 846 for (i = 0; i < n_comp; i++) { 847 /* add in colors */ 848 hihi <<= 5; 849 hihi |= reord[maxCol][i] >> 3; 850 } 851 for (i = 0; i < n_comp; i++) { 852 /* add in colors */ 853 hihi <<= 5; 854 hihi |= reord[minCol][i] >> 3; 855 } 856 cc[3] = hihi; 857 cc[0] = cc[1] = cc[2] = 0; 858 859 /* compute interpolation vector */ 860 if (minCol != maxCol) { 861 MAKEIVEC(n_vect, n_comp, iv, b, reord[minCol], reord[maxCol]); 862 } 863 864 /* add in texels */ 865 for (k = N_TEXELS - 1; k >= 0; k--) { 866 GLint t = k * 3; 867 GLuint *kk = (GLuint *)((char *)cc + t / 8); 868 GLint texel = n_vect + 1; /* transparent black */ 869 870 if (!ISTBLACK(input[k])) { 871 if (minCol != maxCol) { 872 /* interpolate color */ 873 CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); 874 /* add in texel */ 875 kk[0] |= texel << (t & 7); 876 } 877 } else { 878 /* add in texel */ 879 kk[0] |= texel << (t & 7); 880 } 881 } 882} 883 884 885static void 886fxt1_quantize_MIXED1 (GLuint *cc, 887 GLubyte input[N_TEXELS][MAX_COMP]) 888{ 889 const GLint n_vect = 2; /* highest vector number in each microtile */ 890 const GLint n_comp = 3; /* 3 components: R, G, B */ 891 GLubyte vec[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */ 892 GLfloat b, iv[MAX_COMP]; /* interpolation vector */ 893 GLint i, j, k; 894 Fx64 hi; /* high quadword */ 895 GLuint lohi, lolo; /* low quadword: hi dword, lo dword */ 896 897 GLint minSum; 898 GLint maxSum; 899 GLint minColL = 0, maxColL = -1; 900 GLint minColR = 0, maxColR = -1; 901 902 /* Our solution here is to find the darkest and brightest colors in 903 * the 4x4 tile and use those as the two representative colors. 904 * There are probably better algorithms to use (histogram-based). 905 */ 906 minSum = 2000; /* big enough */ 907 maxSum = -1; /* small enough */ 908 for (k = 0; k < N_TEXELS / 2; k++) { 909 if (!ISTBLACK(input[k])) { 910 GLint sum = 0; 911 for (i = 0; i < n_comp; i++) { 912 sum += input[k][i]; 913 } 914 if (minSum > sum) { 915 minSum = sum; 916 minColL = k; 917 } 918 if (maxSum < sum) { 919 maxSum = sum; 920 maxColL = k; 921 } 922 } 923 } 924 minSum = 2000; /* big enough */ 925 maxSum = -1; /* small enough */ 926 for (; k < N_TEXELS; k++) { 927 if (!ISTBLACK(input[k])) { 928 GLint sum = 0; 929 for (i = 0; i < n_comp; i++) { 930 sum += input[k][i]; 931 } 932 if (minSum > sum) { 933 minSum = sum; 934 minColR = k; 935 } 936 if (maxSum < sum) { 937 maxSum = sum; 938 maxColR = k; 939 } 940 } 941 } 942 943 /* left microtile */ 944 if (maxColL == -1) { 945 /* all transparent black */ 946 cc[0] = ~0u; 947 for (i = 0; i < n_comp; i++) { 948 vec[0][i] = 0; 949 vec[1][i] = 0; 950 } 951 } else { 952 cc[0] = 0; 953 for (i = 0; i < n_comp; i++) { 954 vec[0][i] = input[minColL][i]; 955 vec[1][i] = input[maxColL][i]; 956 } 957 if (minColL != maxColL) { 958 /* compute interpolation vector */ 959 MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]); 960 961 /* add in texels */ 962 lolo = 0; 963 for (k = N_TEXELS / 2 - 1; k >= 0; k--) { 964 GLint texel = n_vect + 1; /* transparent black */ 965 if (!ISTBLACK(input[k])) { 966 /* interpolate color */ 967 CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); 968 } 969 /* add in texel */ 970 lolo <<= 2; 971 lolo |= texel; 972 } 973 cc[0] = lolo; 974 } 975 } 976 977 /* right microtile */ 978 if (maxColR == -1) { 979 /* all transparent black */ 980 cc[1] = ~0u; 981 for (i = 0; i < n_comp; i++) { 982 vec[2][i] = 0; 983 vec[3][i] = 0; 984 } 985 } else { 986 cc[1] = 0; 987 for (i = 0; i < n_comp; i++) { 988 vec[2][i] = input[minColR][i]; 989 vec[3][i] = input[maxColR][i]; 990 } 991 if (minColR != maxColR) { 992 /* compute interpolation vector */ 993 MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]); 994 995 /* add in texels */ 996 lohi = 0; 997 for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) { 998 GLint texel = n_vect + 1; /* transparent black */ 999 if (!ISTBLACK(input[k])) { 1000 /* interpolate color */ 1001 CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); 1002 } 1003 /* add in texel */ 1004 lohi <<= 2; 1005 lohi |= texel; 1006 } 1007 cc[1] = lohi; 1008 } 1009 } 1010 1011 FX64_MOV32(hi, 9 | (vec[3][GCOMP] & 4) | ((vec[1][GCOMP] >> 1) & 2)); /* chroma = "1" */ 1012 for (j = 2 * 2 - 1; j >= 0; j--) { 1013 for (i = 0; i < n_comp; i++) { 1014 /* add in colors */ 1015 FX64_SHL(hi, 5); 1016 FX64_OR32(hi, vec[j][i] >> 3); 1017 } 1018 } 1019 ((Fx64 *)cc)[1] = hi; 1020} 1021 1022 1023static void 1024fxt1_quantize_MIXED0 (GLuint *cc, 1025 GLubyte input[N_TEXELS][MAX_COMP]) 1026{ 1027 const GLint n_vect = 3; /* highest vector number in each microtile */ 1028 const GLint n_comp = 3; /* 3 components: R, G, B */ 1029 GLubyte vec[2 * 2][MAX_COMP]; /* 2 extrema for each sub-block */ 1030 GLfloat b, iv[MAX_COMP]; /* interpolation vector */ 1031 GLint i, j, k; 1032 Fx64 hi; /* high quadword */ 1033 GLuint lohi, lolo; /* low quadword: hi dword, lo dword */ 1034 1035 GLint minColL = 0, maxColL = 0; 1036 GLint minColR = 0, maxColR = 0; 1037#if 0 1038 GLint minSum; 1039 GLint maxSum; 1040 1041 /* Our solution here is to find the darkest and brightest colors in 1042 * the 4x4 tile and use those as the two representative colors. 1043 * There are probably better algorithms to use (histogram-based). 1044 */ 1045 minSum = 2000; /* big enough */ 1046 maxSum = -1; /* small enough */ 1047 for (k = 0; k < N_TEXELS / 2; k++) { 1048 GLint sum = 0; 1049 for (i = 0; i < n_comp; i++) { 1050 sum += input[k][i]; 1051 } 1052 if (minSum > sum) { 1053 minSum = sum; 1054 minColL = k; 1055 } 1056 if (maxSum < sum) { 1057 maxSum = sum; 1058 maxColL = k; 1059 } 1060 } 1061 minSum = 2000; /* big enough */ 1062 maxSum = -1; /* small enough */ 1063 for (; k < N_TEXELS; k++) { 1064 GLint sum = 0; 1065 for (i = 0; i < n_comp; i++) { 1066 sum += input[k][i]; 1067 } 1068 if (minSum > sum) { 1069 minSum = sum; 1070 minColR = k; 1071 } 1072 if (maxSum < sum) { 1073 maxSum = sum; 1074 maxColR = k; 1075 } 1076 } 1077#else 1078 GLint minVal; 1079 GLint maxVal; 1080 GLint maxVarL = fxt1_variance(NULL, input, n_comp, N_TEXELS / 2); 1081 GLint maxVarR = fxt1_variance(NULL, &input[N_TEXELS / 2], n_comp, N_TEXELS / 2); 1082 1083 /* Scan the channel with max variance for lo & hi 1084 * and use those as the two representative colors. 1085 */ 1086 minVal = 2000; /* big enough */ 1087 maxVal = -1; /* small enough */ 1088 for (k = 0; k < N_TEXELS / 2; k++) { 1089 GLint t = input[k][maxVarL]; 1090 if (minVal > t) { 1091 minVal = t; 1092 minColL = k; 1093 } 1094 if (maxVal < t) { 1095 maxVal = t; 1096 maxColL = k; 1097 } 1098 } 1099 minVal = 2000; /* big enough */ 1100 maxVal = -1; /* small enough */ 1101 for (; k < N_TEXELS; k++) { 1102 GLint t = input[k][maxVarR]; 1103 if (minVal > t) { 1104 minVal = t; 1105 minColR = k; 1106 } 1107 if (maxVal < t) { 1108 maxVal = t; 1109 maxColR = k; 1110 } 1111 } 1112#endif 1113 1114 /* left microtile */ 1115 cc[0] = 0; 1116 for (i = 0; i < n_comp; i++) { 1117 vec[0][i] = input[minColL][i]; 1118 vec[1][i] = input[maxColL][i]; 1119 } 1120 if (minColL != maxColL) { 1121 /* compute interpolation vector */ 1122 MAKEIVEC(n_vect, n_comp, iv, b, vec[0], vec[1]); 1123 1124 /* add in texels */ 1125 lolo = 0; 1126 for (k = N_TEXELS / 2 - 1; k >= 0; k--) { 1127 GLint texel; 1128 /* interpolate color */ 1129 CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); 1130 /* add in texel */ 1131 lolo <<= 2; 1132 lolo |= texel; 1133 } 1134 1135 /* funky encoding for LSB of green */ 1136 if ((GLint)((lolo >> 1) & 1) != (((vec[1][GCOMP] ^ vec[0][GCOMP]) >> 2) & 1)) { 1137 for (i = 0; i < n_comp; i++) { 1138 vec[1][i] = input[minColL][i]; 1139 vec[0][i] = input[maxColL][i]; 1140 } 1141 lolo = ~lolo; 1142 } 1143 1144 cc[0] = lolo; 1145 } 1146 1147 /* right microtile */ 1148 cc[1] = 0; 1149 for (i = 0; i < n_comp; i++) { 1150 vec[2][i] = input[minColR][i]; 1151 vec[3][i] = input[maxColR][i]; 1152 } 1153 if (minColR != maxColR) { 1154 /* compute interpolation vector */ 1155 MAKEIVEC(n_vect, n_comp, iv, b, vec[2], vec[3]); 1156 1157 /* add in texels */ 1158 lohi = 0; 1159 for (k = N_TEXELS - 1; k >= N_TEXELS / 2; k--) { 1160 GLint texel; 1161 /* interpolate color */ 1162 CALCCDOT(texel, n_vect, n_comp, iv, b, input[k]); 1163 /* add in texel */ 1164 lohi <<= 2; 1165 lohi |= texel; 1166 } 1167 1168 /* funky encoding for LSB of green */ 1169 if ((GLint)((lohi >> 1) & 1) != (((vec[3][GCOMP] ^ vec[2][GCOMP]) >> 2) & 1)) { 1170 for (i = 0; i < n_comp; i++) { 1171 vec[3][i] = input[minColR][i]; 1172 vec[2][i] = input[maxColR][i]; 1173 } 1174 lohi = ~lohi; 1175 } 1176 1177 cc[1] = lohi; 1178 } 1179 1180 FX64_MOV32(hi, 8 | (vec[3][GCOMP] & 4) | ((vec[1][GCOMP] >> 1) & 2)); /* chroma = "1" */ 1181 for (j = 2 * 2 - 1; j >= 0; j--) { 1182 for (i = 0; i < n_comp; i++) { 1183 /* add in colors */ 1184 FX64_SHL(hi, 5); 1185 FX64_OR32(hi, vec[j][i] >> 3); 1186 } 1187 } 1188 ((Fx64 *)cc)[1] = hi; 1189} 1190 1191 1192static void 1193fxt1_quantize (GLuint *cc, const GLubyte *lines[], GLint comps) 1194{ 1195 GLint trualpha; 1196 GLubyte reord[N_TEXELS][MAX_COMP]; 1197 1198 GLubyte input[N_TEXELS][MAX_COMP]; 1199 GLint i, k, l; 1200 1201 if (comps == 3) { 1202 /* make the whole block opaque */ 1203 memset(input, -1, sizeof(input)); 1204 } 1205 1206 /* 8 texels each line */ 1207 for (l = 0; l < 4; l++) { 1208 for (k = 0; k < 4; k++) { 1209 for (i = 0; i < comps; i++) { 1210 input[k + l * 4][i] = *lines[l]++; 1211 } 1212 } 1213 for (; k < 8; k++) { 1214 for (i = 0; i < comps; i++) { 1215 input[k + l * 4 + 12][i] = *lines[l]++; 1216 } 1217 } 1218 } 1219 1220 /* block layout: 1221 * 00, 01, 02, 03, 08, 09, 0a, 0b 1222 * 10, 11, 12, 13, 18, 19, 1a, 1b 1223 * 04, 05, 06, 07, 0c, 0d, 0e, 0f 1224 * 14, 15, 16, 17, 1c, 1d, 1e, 1f 1225 */ 1226 1227 /* [dBorca] 1228 * stupidity flows forth from this 1229 */ 1230 l = N_TEXELS; 1231 trualpha = 0; 1232 if (comps == 4) { 1233 /* skip all transparent black texels */ 1234 l = 0; 1235 for (k = 0; k < N_TEXELS; k++) { 1236 /* test all components against 0 */ 1237 if (!ISTBLACK(input[k])) { 1238 /* texel is not transparent black */ 1239 COPY_4UBV(reord[l], input[k]); 1240 if (reord[l][ACOMP] < (255 - ALPHA_TS)) { 1241 /* non-opaque texel */ 1242 trualpha = !0; 1243 } 1244 l++; 1245 } 1246 } 1247 } 1248 1249#if 0 1250 if (trualpha) { 1251 fxt1_quantize_ALPHA0(cc, input, reord, l); 1252 } else if (l == 0) { 1253 cc[0] = cc[1] = cc[2] = -1; 1254 cc[3] = 0; 1255 } else if (l < N_TEXELS) { 1256 fxt1_quantize_HI(cc, input, reord, l); 1257 } else { 1258 fxt1_quantize_CHROMA(cc, input); 1259 } 1260 (void)fxt1_quantize_ALPHA1; 1261 (void)fxt1_quantize_MIXED1; 1262 (void)fxt1_quantize_MIXED0; 1263#else 1264 if (trualpha) { 1265 fxt1_quantize_ALPHA1(cc, input); 1266 } else if (l == 0) { 1267 cc[0] = cc[1] = cc[2] = ~0u; 1268 cc[3] = 0; 1269 } else if (l < N_TEXELS) { 1270 fxt1_quantize_MIXED1(cc, input); 1271 } else { 1272 fxt1_quantize_MIXED0(cc, input); 1273 } 1274 (void)fxt1_quantize_ALPHA0; 1275 (void)fxt1_quantize_HI; 1276 (void)fxt1_quantize_CHROMA; 1277#endif 1278} 1279 1280 1281 1282/** 1283 * Upscale an image by replication, not (typical) stretching. 1284 * We use this when the image width or height is less than a 1285 * certain size (4, 8) and we need to upscale an image. 1286 */ 1287static void 1288upscale_teximage2d(GLsizei inWidth, GLsizei inHeight, 1289 GLsizei outWidth, GLsizei outHeight, 1290 GLint comps, const GLubyte *src, GLint srcRowStride, 1291 GLubyte *dest ) 1292{ 1293 GLint i, j, k; 1294 1295 ASSERT(outWidth >= inWidth); 1296 ASSERT(outHeight >= inHeight); 1297#if 0 1298 ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2); 1299 ASSERT((outWidth & 3) == 0); 1300 ASSERT((outHeight & 3) == 0); 1301#endif 1302 1303 for (i = 0; i < outHeight; i++) { 1304 const GLint ii = i % inHeight; 1305 for (j = 0; j < outWidth; j++) { 1306 const GLint jj = j % inWidth; 1307 for (k = 0; k < comps; k++) { 1308 dest[(i * outWidth + j) * comps + k] 1309 = src[ii * srcRowStride + jj * comps + k]; 1310 } 1311 } 1312 } 1313} 1314 1315 1316static void 1317fxt1_encode (GLuint width, GLuint height, GLint comps, 1318 const void *source, GLint srcRowStride, 1319 void *dest, GLint destRowStride) 1320{ 1321 GLuint x, y; 1322 const GLubyte *data; 1323 GLuint *encoded = (GLuint *)dest; 1324 void *newSource = NULL; 1325 1326 assert(comps == 3 || comps == 4); 1327 1328 /* Replicate image if width is not M8 or height is not M4 */ 1329 if ((width & 7) | (height & 3)) { 1330 GLint newWidth = (width + 7) & ~7; 1331 GLint newHeight = (height + 3) & ~3; 1332 newSource = malloc(comps * newWidth * newHeight * sizeof(GLubyte)); 1333 if (!newSource) { 1334 GET_CURRENT_CONTEXT(ctx); 1335 _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture compression"); 1336 goto cleanUp; 1337 } 1338 upscale_teximage2d(width, height, newWidth, newHeight, 1339 comps, (const GLubyte *) source, 1340 srcRowStride, (GLubyte *) newSource); 1341 source = newSource; 1342 width = newWidth; 1343 height = newHeight; 1344 srcRowStride = comps * newWidth; 1345 } 1346 1347 data = (const GLubyte *) source; 1348 destRowStride = (destRowStride - width * 2) / 4; 1349 for (y = 0; y < height; y += 4) { 1350 GLuint offs = 0 + (y + 0) * srcRowStride; 1351 for (x = 0; x < width; x += 8) { 1352 const GLubyte *lines[4]; 1353 lines[0] = &data[offs]; 1354 lines[1] = lines[0] + srcRowStride; 1355 lines[2] = lines[1] + srcRowStride; 1356 lines[3] = lines[2] + srcRowStride; 1357 offs += 8 * comps; 1358 fxt1_quantize(encoded, lines, comps); 1359 /* 128 bits per 8x4 block */ 1360 encoded += 4; 1361 } 1362 encoded += destRowStride; 1363 } 1364 1365 cleanUp: 1366 if (newSource != NULL) { 1367 free(newSource); 1368 } 1369} 1370 1371 1372/***************************************************************************\ 1373 * FXT1 decoder 1374 * 1375 * The decoder is based on GL_3DFX_texture_compression_FXT1 1376 * specification and serves as a concept for the encoder. 1377\***************************************************************************/ 1378 1379 1380/* lookup table for scaling 5 bit colors up to 8 bits */ 1381static const GLubyte _rgb_scale_5[] = { 1382 0, 8, 16, 25, 33, 41, 49, 58, 1383 66, 74, 82, 90, 99, 107, 115, 123, 1384 132, 140, 148, 156, 165, 173, 181, 189, 1385 197, 206, 214, 222, 230, 239, 247, 255 1386}; 1387 1388/* lookup table for scaling 6 bit colors up to 8 bits */ 1389static const GLubyte _rgb_scale_6[] = { 1390 0, 4, 8, 12, 16, 20, 24, 28, 1391 32, 36, 40, 45, 49, 53, 57, 61, 1392 65, 69, 73, 77, 81, 85, 89, 93, 1393 97, 101, 105, 109, 113, 117, 121, 125, 1394 130, 134, 138, 142, 146, 150, 154, 158, 1395 162, 166, 170, 174, 178, 182, 186, 190, 1396 194, 198, 202, 206, 210, 215, 219, 223, 1397 227, 231, 235, 239, 243, 247, 251, 255 1398}; 1399 1400 1401#define CC_SEL(cc, which) (((GLuint *)(cc))[(which) / 32] >> ((which) & 31)) 1402#define UP5(c) _rgb_scale_5[(c) & 31] 1403#define UP6(c, b) _rgb_scale_6[(((c) & 31) << 1) | ((b) & 1)] 1404#define LERP(n, t, c0, c1) (((n) - (t)) * (c0) + (t) * (c1) + (n) / 2) / (n) 1405 1406 1407static void 1408fxt1_decode_1HI (const GLubyte *code, GLint t, GLubyte *rgba) 1409{ 1410 const GLuint *cc; 1411 1412 t *= 3; 1413 cc = (const GLuint *)(code + t / 8); 1414 t = (cc[0] >> (t & 7)) & 7; 1415 1416 if (t == 7) { 1417 rgba[RCOMP] = rgba[GCOMP] = rgba[BCOMP] = rgba[ACOMP] = 0; 1418 } else { 1419 GLubyte r, g, b; 1420 cc = (const GLuint *)(code + 12); 1421 if (t == 0) { 1422 b = UP5(CC_SEL(cc, 0)); 1423 g = UP5(CC_SEL(cc, 5)); 1424 r = UP5(CC_SEL(cc, 10)); 1425 } else if (t == 6) { 1426 b = UP5(CC_SEL(cc, 15)); 1427 g = UP5(CC_SEL(cc, 20)); 1428 r = UP5(CC_SEL(cc, 25)); 1429 } else { 1430 b = LERP(6, t, UP5(CC_SEL(cc, 0)), UP5(CC_SEL(cc, 15))); 1431 g = LERP(6, t, UP5(CC_SEL(cc, 5)), UP5(CC_SEL(cc, 20))); 1432 r = LERP(6, t, UP5(CC_SEL(cc, 10)), UP5(CC_SEL(cc, 25))); 1433 } 1434 rgba[RCOMP] = r; 1435 rgba[GCOMP] = g; 1436 rgba[BCOMP] = b; 1437 rgba[ACOMP] = 255; 1438 } 1439} 1440 1441 1442static void 1443fxt1_decode_1CHROMA (const GLubyte *code, GLint t, GLubyte *rgba) 1444{ 1445 const GLuint *cc; 1446 GLuint kk; 1447 1448 cc = (const GLuint *)code; 1449 if (t & 16) { 1450 cc++; 1451 t &= 15; 1452 } 1453 t = (cc[0] >> (t * 2)) & 3; 1454 1455 t *= 15; 1456 cc = (const GLuint *)(code + 8 + t / 8); 1457 kk = cc[0] >> (t & 7); 1458 rgba[BCOMP] = UP5(kk); 1459 rgba[GCOMP] = UP5(kk >> 5); 1460 rgba[RCOMP] = UP5(kk >> 10); 1461 rgba[ACOMP] = 255; 1462} 1463 1464 1465static void 1466fxt1_decode_1MIXED (const GLubyte *code, GLint t, GLubyte *rgba) 1467{ 1468 const GLuint *cc; 1469 GLuint col[2][3]; 1470 GLint glsb, selb; 1471 1472 cc = (const GLuint *)code; 1473 if (t & 16) { 1474 t &= 15; 1475 t = (cc[1] >> (t * 2)) & 3; 1476 /* col 2 */ 1477 col[0][BCOMP] = (*(const GLuint *)(code + 11)) >> 6; 1478 col[0][GCOMP] = CC_SEL(cc, 99); 1479 col[0][RCOMP] = CC_SEL(cc, 104); 1480 /* col 3 */ 1481 col[1][BCOMP] = CC_SEL(cc, 109); 1482 col[1][GCOMP] = CC_SEL(cc, 114); 1483 col[1][RCOMP] = CC_SEL(cc, 119); 1484 glsb = CC_SEL(cc, 126); 1485 selb = CC_SEL(cc, 33); 1486 } else { 1487 t = (cc[0] >> (t * 2)) & 3; 1488 /* col 0 */ 1489 col[0][BCOMP] = CC_SEL(cc, 64); 1490 col[0][GCOMP] = CC_SEL(cc, 69); 1491 col[0][RCOMP] = CC_SEL(cc, 74); 1492 /* col 1 */ 1493 col[1][BCOMP] = CC_SEL(cc, 79); 1494 col[1][GCOMP] = CC_SEL(cc, 84); 1495 col[1][RCOMP] = CC_SEL(cc, 89); 1496 glsb = CC_SEL(cc, 125); 1497 selb = CC_SEL(cc, 1); 1498 } 1499 1500 if (CC_SEL(cc, 124) & 1) { 1501 /* alpha[0] == 1 */ 1502 1503 if (t == 3) { 1504 /* zero */ 1505 rgba[RCOMP] = rgba[BCOMP] = rgba[GCOMP] = rgba[ACOMP] = 0; 1506 } else { 1507 GLubyte r, g, b; 1508 if (t == 0) { 1509 b = UP5(col[0][BCOMP]); 1510 g = UP5(col[0][GCOMP]); 1511 r = UP5(col[0][RCOMP]); 1512 } else if (t == 2) { 1513 b = UP5(col[1][BCOMP]); 1514 g = UP6(col[1][GCOMP], glsb); 1515 r = UP5(col[1][RCOMP]); 1516 } else { 1517 b = (UP5(col[0][BCOMP]) + UP5(col[1][BCOMP])) / 2; 1518 g = (UP5(col[0][GCOMP]) + UP6(col[1][GCOMP], glsb)) / 2; 1519 r = (UP5(col[0][RCOMP]) + UP5(col[1][RCOMP])) / 2; 1520 } 1521 rgba[RCOMP] = r; 1522 rgba[GCOMP] = g; 1523 rgba[BCOMP] = b; 1524 rgba[ACOMP] = 255; 1525 } 1526 } else { 1527 /* alpha[0] == 0 */ 1528 GLubyte r, g, b; 1529 if (t == 0) { 1530 b = UP5(col[0][BCOMP]); 1531 g = UP6(col[0][GCOMP], glsb ^ selb); 1532 r = UP5(col[0][RCOMP]); 1533 } else if (t == 3) { 1534 b = UP5(col[1][BCOMP]); 1535 g = UP6(col[1][GCOMP], glsb); 1536 r = UP5(col[1][RCOMP]); 1537 } else { 1538 b = LERP(3, t, UP5(col[0][BCOMP]), UP5(col[1][BCOMP])); 1539 g = LERP(3, t, UP6(col[0][GCOMP], glsb ^ selb), 1540 UP6(col[1][GCOMP], glsb)); 1541 r = LERP(3, t, UP5(col[0][RCOMP]), UP5(col[1][RCOMP])); 1542 } 1543 rgba[RCOMP] = r; 1544 rgba[GCOMP] = g; 1545 rgba[BCOMP] = b; 1546 rgba[ACOMP] = 255; 1547 } 1548} 1549 1550 1551static void 1552fxt1_decode_1ALPHA (const GLubyte *code, GLint t, GLubyte *rgba) 1553{ 1554 const GLuint *cc; 1555 GLubyte r, g, b, a; 1556 1557 cc = (const GLuint *)code; 1558 if (CC_SEL(cc, 124) & 1) { 1559 /* lerp == 1 */ 1560 GLuint col0[4]; 1561 1562 if (t & 16) { 1563 t &= 15; 1564 t = (cc[1] >> (t * 2)) & 3; 1565 /* col 2 */ 1566 col0[BCOMP] = (*(const GLuint *)(code + 11)) >> 6; 1567 col0[GCOMP] = CC_SEL(cc, 99); 1568 col0[RCOMP] = CC_SEL(cc, 104); 1569 col0[ACOMP] = CC_SEL(cc, 119); 1570 } else { 1571 t = (cc[0] >> (t * 2)) & 3; 1572 /* col 0 */ 1573 col0[BCOMP] = CC_SEL(cc, 64); 1574 col0[GCOMP] = CC_SEL(cc, 69); 1575 col0[RCOMP] = CC_SEL(cc, 74); 1576 col0[ACOMP] = CC_SEL(cc, 109); 1577 } 1578 1579 if (t == 0) { 1580 b = UP5(col0[BCOMP]); 1581 g = UP5(col0[GCOMP]); 1582 r = UP5(col0[RCOMP]); 1583 a = UP5(col0[ACOMP]); 1584 } else if (t == 3) { 1585 b = UP5(CC_SEL(cc, 79)); 1586 g = UP5(CC_SEL(cc, 84)); 1587 r = UP5(CC_SEL(cc, 89)); 1588 a = UP5(CC_SEL(cc, 114)); 1589 } else { 1590 b = LERP(3, t, UP5(col0[BCOMP]), UP5(CC_SEL(cc, 79))); 1591 g = LERP(3, t, UP5(col0[GCOMP]), UP5(CC_SEL(cc, 84))); 1592 r = LERP(3, t, UP5(col0[RCOMP]), UP5(CC_SEL(cc, 89))); 1593 a = LERP(3, t, UP5(col0[ACOMP]), UP5(CC_SEL(cc, 114))); 1594 } 1595 } else { 1596 /* lerp == 0 */ 1597 1598 if (t & 16) { 1599 cc++; 1600 t &= 15; 1601 } 1602 t = (cc[0] >> (t * 2)) & 3; 1603 1604 if (t == 3) { 1605 /* zero */ 1606 r = g = b = a = 0; 1607 } else { 1608 GLuint kk; 1609 cc = (const GLuint *)code; 1610 a = UP5(cc[3] >> (t * 5 + 13)); 1611 t *= 15; 1612 cc = (const GLuint *)(code + 8 + t / 8); 1613 kk = cc[0] >> (t & 7); 1614 b = UP5(kk); 1615 g = UP5(kk >> 5); 1616 r = UP5(kk >> 10); 1617 } 1618 } 1619 rgba[RCOMP] = r; 1620 rgba[GCOMP] = g; 1621 rgba[BCOMP] = b; 1622 rgba[ACOMP] = a; 1623} 1624 1625 1626void 1627fxt1_decode_1 (const void *texture, GLint stride, /* in pixels */ 1628 GLint i, GLint j, GLubyte *rgba) 1629{ 1630 static void (*decode_1[]) (const GLubyte *, GLint, GLubyte *) = { 1631 fxt1_decode_1HI, /* cc-high = "00?" */ 1632 fxt1_decode_1HI, /* cc-high = "00?" */ 1633 fxt1_decode_1CHROMA, /* cc-chroma = "010" */ 1634 fxt1_decode_1ALPHA, /* alpha = "011" */ 1635 fxt1_decode_1MIXED, /* mixed = "1??" */ 1636 fxt1_decode_1MIXED, /* mixed = "1??" */ 1637 fxt1_decode_1MIXED, /* mixed = "1??" */ 1638 fxt1_decode_1MIXED /* mixed = "1??" */ 1639 }; 1640 1641 const GLubyte *code = (const GLubyte *)texture + 1642 ((j / 4) * (stride / 8) + (i / 8)) * 16; 1643 GLint mode = CC_SEL(code, 125); 1644 GLint t = i & 7; 1645 1646 if (t & 4) { 1647 t += 12; 1648 } 1649 t += (j & 3) * 4; 1650 1651 decode_1[mode](code, t, rgba); 1652} 1653 1654 1655#endif /* FEATURE_texture_fxt1 */ 1656