xref: /reactos/dll/3rdparty/dxtn/txc_fetch_dxtn.c (revision 8540ab04)
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