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