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