1 /* 2 * libtxc_dxtn 3 * Version: 1.0 4 * 5 * Copyright (C) 2004 Roland Scheidegger All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 #include <stdio.h> 26 #include "txc_dxtn.h" 27 28 #define EXP5TO8R(packedcol) \ 29 ((((packedcol) >> 8) & 0xf8) | (((packedcol) >> 13) & 0x7)) 30 31 #define EXP6TO8G(packedcol) \ 32 ((((packedcol) >> 3) & 0xfc) | (((packedcol) >> 9) & 0x3)) 33 34 #define EXP5TO8B(packedcol) \ 35 ((((packedcol) << 3) & 0xf8) | (((packedcol) >> 2) & 0x7)) 36 37 #define EXP4TO8(col) \ 38 ((col) | ((col) << 4)) 39 40 /* inefficient. To be efficient, it would be necessary to decode 16 pixels at once */ 41 42 static void dxt135_decode_imageblock ( const GLubyte *img_block_src, 43 GLint i, GLint j, GLuint dxt_type, GLvoid *texel ) { 44 GLchan *rgba = (GLchan *) texel; 45 const GLushort color0 = img_block_src[0] | (img_block_src[1] << 8); 46 const GLushort color1 = img_block_src[2] | (img_block_src[3] << 8); 47 const GLuint bits = img_block_src[4] | (img_block_src[5] << 8) | 48 (img_block_src[6] << 16) | (img_block_src[7] << 24); 49 /* What about big/little endian? */ 50 GLubyte bit_pos = 2 * (j * 4 + i) ; 51 GLubyte code = (GLubyte) ((bits >> bit_pos) & 3); 52 53 rgba[ACOMP] = CHAN_MAX; 54 switch (code) { 55 case 0: 56 rgba[RCOMP] = UBYTE_TO_CHAN( EXP5TO8R(color0) ); 57 rgba[GCOMP] = UBYTE_TO_CHAN( EXP6TO8G(color0) ); 58 rgba[BCOMP] = UBYTE_TO_CHAN( EXP5TO8B(color0) ); 59 break; 60 case 1: 61 rgba[RCOMP] = UBYTE_TO_CHAN( EXP5TO8R(color1) ); 62 rgba[GCOMP] = UBYTE_TO_CHAN( EXP6TO8G(color1) ); 63 rgba[BCOMP] = UBYTE_TO_CHAN( EXP5TO8B(color1) ); 64 break; 65 case 2: 66 if ((dxt_type > 1) || (color0 > color1)) { 67 rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) * 2 + EXP5TO8R(color1)) / 3) ); 68 rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) * 2 + EXP6TO8G(color1)) / 3) ); 69 rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) * 2 + EXP5TO8B(color1)) / 3) ); 70 } 71 else { 72 rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) + EXP5TO8R(color1)) / 2) ); 73 rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) + EXP6TO8G(color1)) / 2) ); 74 rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) + EXP5TO8B(color1)) / 2) ); 75 } 76 break; 77 case 3: 78 if ((dxt_type > 1) || (color0 > color1)) { 79 rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) + EXP5TO8R(color1) * 2) / 3) ); 80 rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) + EXP6TO8G(color1) * 2) / 3) ); 81 rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) + EXP5TO8B(color1) * 2) / 3) ); 82 } 83 else { 84 rgba[RCOMP] = 0; 85 rgba[GCOMP] = 0; 86 rgba[BCOMP] = 0; 87 if (dxt_type == 1) rgba[ACOMP] = UBYTE_TO_CHAN(0); 88 } 89 break; 90 default: 91 /* CANNOT happen (I hope) */ 92 break; 93 } 94 } 95 96 97 void fetch_2d_texel_rgb_dxt1(GLint srcRowStride, const GLubyte *pixdata, 98 GLint i, GLint j, GLvoid *texel) 99 { 100 /* Extract the (i,j) pixel from pixdata and return it 101 * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP]. 102 */ 103 104 const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8); 105 dxt135_decode_imageblock(blksrc, (i&3), (j&3), 0, texel); 106 } 107 108 109 void fetch_2d_texel_rgba_dxt1(GLint srcRowStride, const GLubyte *pixdata, 110 GLint i, GLint j, GLvoid *texel) 111 { 112 /* Extract the (i,j) pixel from pixdata and return it 113 * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP]. 114 */ 115 116 const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8); 117 dxt135_decode_imageblock(blksrc, (i&3), (j&3), 1, texel); 118 } 119 120 void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata, 121 GLint i, GLint j, GLvoid *texel) { 122 123 /* Extract the (i,j) pixel from pixdata and return it 124 * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP]. 125 */ 126 127 GLchan *rgba = (GLchan *) texel; 128 const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16); 129 #if 0 130 /* Simple 32bit version. */ 131 /* that's pretty brain-dead for a single pixel, isn't it? */ 132 const GLubyte bit_pos = 4 * ((j&3) * 4 + (i&3)); 133 const GLuint alpha_low = blksrc[0] | (blksrc[1] << 8) | (blksrc[2] << 16) | (blksrc[3] << 24); 134 const GLuint alpha_high = blksrc[4] | (blksrc[5] << 8) | (blksrc[6] << 16) | (blksrc[7] << 24); 135 136 dxt135_decode_imageblock(blksrc + 8, (i&3), (j&3), 2, texel); 137 if (bit_pos < 32) 138 rgba[ACOMP] = UBYTE_TO_CHAN( (GLubyte)(EXP4TO8((alpha_low >> bit_pos) & 15)) ); 139 else 140 rgba[ACOMP] = UBYTE_TO_CHAN( (GLubyte)(EXP4TO8((alpha_high >> (bit_pos - 32)) & 15)) ); 141 #endif 142 #if 1 143 /* TODO test this! */ 144 const GLubyte anibble = (blksrc[((j&3) * 4 + (i&3)) / 2] >> (4 * (i&1))) & 0xf; 145 dxt135_decode_imageblock(blksrc + 8, (i&3), (j&3), 2, texel); 146 rgba[ACOMP] = UBYTE_TO_CHAN( (GLubyte)(EXP4TO8(anibble)) ); 147 #endif 148 149 } 150 151 void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata, 152 GLint i, GLint j, GLvoid *texel) { 153 154 /* Extract the (i,j) pixel from pixdata and return it 155 * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP]. 156 */ 157 158 GLchan *rgba = (GLchan *) texel; 159 const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16); 160 const GLubyte alpha0 = blksrc[0]; 161 const GLubyte alpha1 = blksrc[1]; 162 #if 0 163 const GLubyte bit_pos = 3 * ((j&3) * 4 + (i&3)); 164 /* simple 32bit version */ 165 const GLuint bits_low = blksrc[2] | (blksrc[3] << 8) | (blksrc[4] << 16) | (blksrc[5] << 24); 166 const GLuint bits_high = blksrc[6] | (blksrc[7] << 8); 167 GLubyte code; 168 169 if (bit_pos < 30) 170 code = (GLubyte) ((bits_low >> bit_pos) & 7); 171 else if (bit_pos == 30) 172 code = (GLubyte) ((bits_low >> 30) & 3) | ((bits_high << 2) & 4); 173 else 174 code = (GLubyte) ((bits_high >> (bit_pos - 32)) & 7); 175 #endif 176 #if 1 177 /* TODO test this! */ 178 const GLubyte bit_pos = ((j&3) * 4 + (i&3)) * 3; 179 const GLubyte acodelow = blksrc[2 + bit_pos / 8]; 180 const GLubyte acodehigh = blksrc[3 + bit_pos / 8]; 181 const GLubyte code = (acodelow >> (bit_pos & 0x7) | 182 (acodehigh << (8 - (bit_pos & 0x7)))) & 0x7; 183 #endif 184 dxt135_decode_imageblock(blksrc + 8, (i&3), (j&3), 2, texel); 185 #if 0 186 if (alpha0 > alpha1) { 187 switch (code) { 188 case 0: 189 rgba[ACOMP] = UBYTE_TO_CHAN( alpha0 ); 190 break; 191 case 1: 192 rgba[ACOMP] = UBYTE_TO_CHAN( alpha1 ); 193 break; 194 case 2: 195 case 3: 196 case 4: 197 case 5: 198 case 6: 199 case 7: 200 rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (8 - code) + (alpha1 * (code - 1))) / 7) ); 201 break; 202 } 203 } 204 else { 205 switch (code) { 206 case 0: 207 rgba[ACOMP] = UBYTE_TO_CHAN( alpha0 ); 208 break; 209 case 1: 210 rgba[ACOMP] = UBYTE_TO_CHAN( alpha1 ); 211 break; 212 case 2: 213 case 3: 214 case 4: 215 case 5: 216 rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (6 - code) + (alpha1 * (code - 1))) / 5) ); 217 break; 218 case 6: 219 rgba[ACOMP] = 0; 220 break; 221 case 7: 222 rgba[ACOMP] = CHAN_MAX; 223 break; 224 } 225 } 226 #endif 227 /* not sure. Which version is faster? */ 228 #if 1 229 /* TODO test this */ 230 if (code == 0) 231 rgba[ACOMP] = UBYTE_TO_CHAN( alpha0 ); 232 else if (code == 1) 233 rgba[ACOMP] = UBYTE_TO_CHAN( alpha1 ); 234 else if (alpha0 > alpha1) 235 rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (8 - code) + (alpha1 * (code - 1))) / 7) ); 236 else if (code < 6) 237 rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (6 - code) + (alpha1 * (code - 1))) / 5) ); 238 else if (code == 6) 239 rgba[ACOMP] = 0; 240 else 241 rgba[ACOMP] = CHAN_MAX; 242 #endif 243 } 244