OSDN Git Service

externally reference all GPLv2 textures too
[android-x86/external-s2tc.git] / s2tc_libtxc_dxtn.cpp
1 extern "C"
2 {
3 #include "txc_dxtn.h"
4 };
5
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include "s2tc_compressor.h"
10
11 void fetch_2d_texel_rgb_dxt1(GLint srcRowStride, const GLubyte *pixdata,
12                              GLint i, GLint j, GLvoid *texel)
13 {
14         // fetches a single texel (i,j) into pixdata (RGB)
15         GLubyte *t = (GLubyte *) texel;
16         const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
17         unsigned int c  = blksrc[0] + 256*blksrc[1];
18         unsigned int c1 = blksrc[2] + 256*blksrc[3];
19         int b = (blksrc[4 + (j % 4)] >> (2 * (i % 4))) & 0x03;
20         switch(b)
21         {
22                 case 0:                        break;
23                 case 1:  c = c1;               break;
24                 case 3:  if(c1 > c) { c = 0;   break; }
25                 default: if((i^j) & 1) c = c1; break;
26         }
27         t[0] = ((c >> 11) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
28         t[1] = ((c >>  5) & 0x3F); t[1] = (t[1] << 2) | (t[1] >> 4);
29         t[2] = ((c      ) & 0x1F); t[2] = (t[2] << 3) | (t[2] >> 2);
30         t[3] = 255;
31 }
32
33 void fetch_2d_texel_rgba_dxt1(GLint srcRowStride, const GLubyte *pixdata,
34                              GLint i, GLint j, GLvoid *texel)
35 {
36         // fetches a single texel (i,j) into pixdata (RGBA)
37         GLubyte *t = (GLubyte *) texel;
38         const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
39         unsigned int c  = blksrc[0] + 256*blksrc[1];
40         unsigned int c1 = blksrc[2] + 256*blksrc[3];
41         int b = (blksrc[4 + (j % 4)] >> (2 * (i % 4))) & 0x03;
42         switch(b)
43         {
44                 case 0:                        t[3] = 255; break;
45                 case 1:  c = c1;               t[3] = 255; break;
46                 case 3:  if(c1 > c) { c = 0;   t[3] =   0; break; }
47                 default: if((i^j) & 1) c = c1; t[3] = 255; break;
48         }
49         t[0] = ((c >> 11) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
50         t[1] = ((c >>  5) & 0x3F); t[1] = (t[1] << 2) | (t[1] >> 4);
51         t[2] = ((c      ) & 0x1F); t[2] = (t[2] << 3) | (t[2] >> 2);
52 }
53
54 void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata,
55                              GLint i, GLint j, GLvoid *texel)
56 {
57         // fetches a single texel (i,j) into pixdata (RGBA)
58         GLubyte *t = (GLubyte *) texel;
59         const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16);
60         unsigned int c  = blksrc[8] + 256*blksrc[9];
61         unsigned int c1 = blksrc[10] + 256*blksrc[11];
62         int b = (blksrc[12 + (j % 4)] >> (2 * (i % 4))) & 0x03;
63         switch(b)
64         {
65                 case 0:                        break;
66                 case 1:  c = c1;               break;
67                 default: if((i^j) & 1) c = c1; break;
68         }
69         t[0] = ((c >> 11) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
70         t[1] = ((c >>  5) & 0x3F); t[1] = (t[1] << 2) | (t[1] >> 4);
71         t[2] = ((c      ) & 0x1F); t[2] = (t[2] << 3) | (t[2] >> 2);
72         int a = (blksrc[(j % 4) * 2 + (i % 4) / 2] >> (4 * (i % 4) % 2)) & 0x0F;
73         t[3] = a | (a << 4);
74 }
75
76 void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata,
77                              GLint i, GLint j, GLvoid *texel)
78 {
79         // fetches a single texel (i,j) into pixdata (RGBA)
80         GLubyte *t = (GLubyte *) texel;
81         const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16);
82         unsigned int c  = blksrc[8] + 256*blksrc[9];
83         unsigned int c1 = blksrc[10] + 256*blksrc[11];
84         int b = (blksrc[12 + (j % 4)] >> (2 * (i % 4))) & 0x03;
85         switch(b)
86         {
87                 case 0:                        break;
88                 case 1:  c = c1;               break;
89                 default: if((i^j) & 1) c = c1; break;
90         }
91         t[0] = ((c >> 11) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
92         t[1] = ((c >>  5) & 0x3F); t[1] = (t[1] << 2) | (t[1] >> 4);
93         t[2] = ((c      ) & 0x1F); t[2] = (t[2] << 3) | (t[2] >> 2);
94
95         unsigned int a  = blksrc[0];
96         unsigned int a1 = blksrc[1];
97         int abit = ((j % 4) * 4 + (i % 4)) * 3;
98         int ab = 0;
99         if(blksrc[(abit / 8) + 2] & (1 << (abit % 8)))
100                 ab |= 1;
101         ++abit;
102         if(blksrc[(abit / 8) + 2] & (1 << (abit % 8)))
103                 ab |= 2;
104         ++abit;
105         if(blksrc[(abit / 8) + 2] & (1 << (abit % 8)))
106                 ab |= 4;
107         switch(ab)
108         {
109                 case 0:                        break;
110                 case 1:  a = a1;               break;
111                 case 6:  a = 0;                break;
112                 case 7:  a = 255;              break;
113                 default: if((i^j) & 1) a = a1; break;
114         }
115         t[3] = a;
116 }
117
118 void tx_compress_dxtn(GLint srccomps, GLint width, GLint height,
119                       const GLubyte *srcPixData, GLenum destformat,
120                       GLubyte *dest, GLint dstRowStride)
121 {
122         // compresses width*height pixels (RGB or RGBA depending on srccomps) at srcPixData (packed) to destformat (dest, dstRowStride)
123
124         GLubyte *blkaddr = dest;
125         GLint numxpixels, numypixels;
126         GLint i, j;
127         GLint dstRowDiff;
128         unsigned char *rgba = (unsigned char *) malloc(width * height * 4);
129         unsigned char *srcaddr;
130         DxtMode dxt;
131
132         switch (destformat) {
133                 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
134                 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
135                         dxt = DXT1;
136                         rgb565_image(rgba, srcPixData, width, height, srccomps, 0, 1);
137                         break;
138                 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
139                         dxt = DXT3;
140                         rgb565_image(rgba, srcPixData, width, height, srccomps, 0, 4);
141                         break;
142                 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
143                         dxt = DXT5;
144                         rgb565_image(rgba, srcPixData, width, height, srccomps, 0, 8);
145                         break;
146                 default:
147                         free(rgba);
148                         fprintf(stderr, "libdxtn: Bad dstFormat %d in tx_compress_dxtn\n", destformat);
149                         return;
150         }
151
152         ColorDistMode cd = WAVG;
153         int nrandom = -1;
154         RefinementMode refine = REFINE_ALWAYS;
155         {
156                 const char *v = getenv("S2TC_COLORDIST_MODE");
157                 if(v)
158                 {
159                         if(!strcasecmp(v, "RGB"))
160                                 cd = RGB;
161                         else if(!strcasecmp(v, "YUV"))
162                                 cd = YUV;
163                         else if(!strcasecmp(v, "SRGB"))
164                                 cd = SRGB;
165                         else if(!strcasecmp(v, "SRGB_MIXED"))
166                                 cd = SRGB_MIXED;
167                         else if(!strcasecmp(v, "LAB"))
168                                 cd = LAB;
169                         else if(!strcasecmp(v, "AVG"))
170                                 cd = AVG;
171                         else if(!strcasecmp(v, "WAVG"))
172                                 cd = WAVG;
173                         else if(!strcasecmp(v, "NORMALMAP"))
174                                 cd = NORMALMAP;
175                         else
176                                 fprintf(stderr, "Invalid color dist mode: %s\n", v);
177                 }
178         }
179         {
180                 const char *v = getenv("S2TC_RANDOM_COLORS");
181                 if(v)
182                         nrandom = atoi(v);
183         }
184         {
185                 const char *v = getenv("S2TC_REFINE_COLORS");
186                 if(v)
187                 {
188                         if(!strcasecmp(v, "NEVER"))
189                                 refine = REFINE_NEVER;
190                         else if(!strcasecmp(v, "ALWAYS"))
191                                 refine = REFINE_ALWAYS;
192                         else if(!strcasecmp(v, "CHECK"))
193                                 refine = REFINE_CHECK;
194                         else
195                                 fprintf(stderr, "Invalid refinement mode: %s\n", v);
196                 }
197         }
198
199         s2tc_encode_block_func_t encode_block = s2tc_encode_block_func(dxt, cd, nrandom, refine);
200         switch (destformat) {
201                 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
202                 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
203                         /* hmm we used to get called without dstRowStride... */
204                         dstRowDiff = dstRowStride >= (width * 2) ? dstRowStride - (((width + 3) & ~3) * 2) : 0;
205                         /*      fprintf(stderr, "dxt1 tex width %d tex height %d dstRowStride %d\n",
206                                 width, height, dstRowStride); */
207                         for (j = 0; j < height; j += 4) {
208                                 if (height > j + 3) numypixels = 4;
209                                 else numypixels = height - j;
210                                 srcaddr = rgba + j * width * 4;
211                                 for (i = 0; i < width; i += 4) {
212                                         if (width > i + 3) numxpixels = 4;
213                                         else numxpixels = width - i;
214                                         encode_block(blkaddr, srcaddr, width, numxpixels, numypixels, nrandom);
215                                         srcaddr += 4 * numxpixels;
216                                         blkaddr += 8;
217                                 }
218                                 blkaddr += dstRowDiff;
219                         }
220                         break;
221                 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
222                         dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) & ~3) * 4) : 0;
223                         /*      fprintf(stderr, "dxt3 tex width %d tex height %d dstRowStride %d\n",
224                                 width, height, dstRowStride); */
225                         for (j = 0; j < height; j += 4) {
226                                 if (height > j + 3) numypixels = 4;
227                                 else numypixels = height - j;
228                                 srcaddr = rgba + j * width * 4;
229                                 for (i = 0; i < width; i += 4) {
230                                         if (width > i + 3) numxpixels = 4;
231                                         else numxpixels = width - i;
232                                         encode_block(blkaddr, srcaddr, width, numxpixels, numypixels, nrandom);
233                                         srcaddr += 4 * numxpixels;
234                                         blkaddr += 16;
235                                 }
236                                 blkaddr += dstRowDiff;
237                         }
238                         break;
239                 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
240                         dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) & ~3) * 4) : 0;
241                         /*      fprintf(stderr, "dxt5 tex width %d tex height %d dstRowStride %d\n",
242                                 width, height, dstRowStride); */
243                         for (j = 0; j < height; j += 4) {
244                                 if (height > j + 3) numypixels = 4;
245                                 else numypixels = height - j;
246                                 srcaddr = rgba + j * width * 4;
247                                 for (i = 0; i < width; i += 4) {
248                                         if (width > i + 3) numxpixels = 4;
249                                         else numxpixels = width - i;
250                                         encode_block(blkaddr, srcaddr, width, numxpixels, numypixels, nrandom);
251                                         srcaddr += 4 * numxpixels;
252                                         blkaddr += 16;
253                                 }
254                                 blkaddr += dstRowDiff;
255                         }
256                         break;
257         }
258
259         free(rgba);
260 }