OSDN Git Service

minor optimization to get rid of some dispatching
[android-x86/external-s2tc.git] / s2tc_libtxc_dxtn.cpp
1 #include "libtxc_dxtn.h"
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include "s2tc_compressor.h"
5
6 void fetch_2d_texel_rgb_dxt1(GLint srcRowStride, const GLubyte *pixdata,
7                              GLint i, GLint j, GLvoid *texel)
8 {
9         // fetches a single texel (i,j) into pixdata (RGB)
10         GLubyte *t = (GLubyte *) texel;
11         const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
12         unsigned int c  = blksrc[0] + 256*blksrc[1];
13         unsigned int c1 = blksrc[2] + 256*blksrc[3];
14         int b = (blksrc[4 + (j % 4)] >> (2 * (i % 4))) & 0x03;
15         switch(b)
16         {
17                 case 0:                         break;
18                 case 1:  c = c1;                break;
19                 case 3:  if(c1 > c) { c = 0;    break; }
20                 default: if(rand() & 1) c = c1; break;
21         }
22         t[2] = ((c >> 11) & 0x1F); t[2] = (t[2] << 3) | (t[2] >> 2);
23         t[1] = ((c >>  5) & 0x3F); t[1] = (t[1] << 2) | (t[1] >> 4);
24         t[0] = ((c      ) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
25 }
26
27 void fetch_2d_texel_rgba_dxt1(GLint srcRowStride, const GLubyte *pixdata,
28                              GLint i, GLint j, GLvoid *texel)
29 {
30         // fetches a single texel (i,j) into pixdata (RGBA)
31         GLubyte *t = (GLubyte *) texel;
32         const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
33         unsigned int c  = blksrc[0] + 256*blksrc[1];
34         unsigned int c1 = blksrc[2] + 256*blksrc[3];
35         int b = (blksrc[4 + (j % 4)] >> (2 * (i % 4))) & 0x03;
36         switch(b)
37         {
38                 case 0:                         t[3] = 255; break;
39                 case 1:  c = c1;                t[3] = 255; break;
40                 case 3:  if(c1 > c) { c = 0;    t[3] =   0; break; }
41                 default: if(rand() & 1) c = c1; t[3] = 255; break;
42         }
43         t[2] = ((c >> 11) & 0x1F); t[2] = (t[2] << 3) | (t[2] >> 2);
44         t[1] = ((c >>  5) & 0x3F); t[1] = (t[1] << 2) | (t[1] >> 4);
45         t[0] = ((c      ) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
46 }
47
48 void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata,
49                              GLint i, GLint j, GLvoid *texel)
50 {
51         // fetches a single texel (i,j) into pixdata (RGBA)
52         GLubyte *t = (GLubyte *) texel;
53         const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
54         unsigned int c  = blksrc[8] + 256*blksrc[9];
55         unsigned int c1 = blksrc[10] + 256*blksrc[11];
56         int b = (blksrc[12 + (j % 4)] >> (2 * (i % 4))) & 0x03;
57         switch(b)
58         {
59                 case 0:                         break;
60                 case 1:  c = c1;                break;
61                 default: if(rand() & 1) c = c1; break;
62         }
63         t[2] = ((c >> 11) & 0x1F); t[2] = (t[2] << 3) | (t[2] >> 2);
64         t[1] = ((c >>  5) & 0x3F); t[1] = (t[1] << 2) | (t[1] >> 4);
65         t[0] = ((c      ) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
66         int a = (blksrc[(j % 4) * 2 + (i % 4) / 2] >> (4 * (i % 4) % 2)) & 0x0F;
67         t[3] = a | (a << 4);
68 }
69
70 void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata,
71                              GLint i, GLint j, GLvoid *texel)
72 {
73         // fetches a single texel (i,j) into pixdata (RGBA)
74         GLubyte *t = (GLubyte *) texel;
75         const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
76         unsigned int c  = blksrc[8] + 256*blksrc[9];
77         unsigned int c1 = blksrc[10] + 256*blksrc[11];
78         int b = (blksrc[12 + (j % 4)] >> (2 * (i % 4))) & 0x03;
79         switch(b)
80         {
81                 case 0:                         break;
82                 case 1:  c = c1;                break;
83                 default: if(rand() & 1) c = c1; break;
84         }
85         t[2] = ((c >> 11) & 0x1F); t[2] = (t[2] << 3) | (t[2] >> 2);
86         t[1] = ((c >>  5) & 0x3F); t[1] = (t[1] << 2) | (t[1] >> 4);
87         t[0] = ((c      ) & 0x1F); t[0] = (t[0] << 3) | (t[0] >> 2);
88
89         unsigned int a  = blksrc[0];
90         unsigned int a1 = blksrc[1];
91         int abit = ((j % 4) * 4 + (i % 4)) * 3;
92         int ab = 0;
93         if(blksrc[(abit / 8)] & (1 << (abit % 8)))
94                 ab |= 1;
95         ++abit;
96         if(blksrc[(abit / 8)] & (1 << (abit % 8)))
97                 ab |= 2;
98         ++abit;
99         if(blksrc[(abit / 8)] & (1 << (abit % 8)))
100                 ab |= 4;
101         switch(ab)
102         {
103                 case 0:                         break;
104                 case 1:  a = a1;                break;
105                 case 6:  a = 0;                 break;
106                 case 7:  a = 255;               break;
107                 default: if(rand() & 1) a = a1; break;
108         }
109         t[3] = a;
110 }
111
112 void tx_compress_dxtn(GLint srccomps, GLint width, GLint height,
113                       const GLubyte *srcPixData, GLenum destFormat,
114                       GLubyte *dest, GLint dstRowStride)
115 {
116         // compresses width*height pixels (RGB or RGBA depending on srccomps) at srcPixData (packed) to destformat (dest, dstRowStride)
117
118         GLubyte *blkaddr = dest;
119         GLint numxpixels, numypixels;
120         GLint i, j;
121         GLint dstRowDiff;
122         unsigned char *rgba = (unsigned char *) malloc(width * height * 4);
123         unsigned char *srcaddr;
124
125         switch (destFormat) {
126                 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
127                 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
128                         rgb565_image(rgba, srcPixData, width, height, srccomps, 0, 1);
129                         break;
130                 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
131                         rgb565_image(rgba, srcPixData, width, height, srccomps, 0, 4);
132                         break;
133                 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
134                         rgb565_image(rgba, srcPixData, width, height, srccomps, 0, 8);
135                         break;
136                 default:
137                         free(rgba);
138                         fprintf(stderr, "libdxtn: Bad dstFormat %d in tx_compress_dxtn\n", destFormat);
139                         return;
140         }
141
142         s2tc_encode_block_func_t encode_block;
143         switch (destFormat) {
144                 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
145                 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
146                         /* hmm we used to get called without dstRowStride... */
147                         dstRowDiff = dstRowStride >= (width * 2) ? dstRowStride - (((width + 3) & ~3) * 2) : 0;
148                         /*      fprintf(stderr, "dxt1 tex width %d tex height %d dstRowStride %d\n",
149                                 width, height, dstRowStride); */
150                         encode_block = s2tc_encode_block_func(DXT1, WAVG, -1);
151                         for (j = 0; j < height; j += 4) {
152                                 if (height > j + 3) numypixels = 4;
153                                 else numypixels = height - j;
154                                 srcaddr = rgba + j * width * 4;
155                                 for (i = 0; i < width; i += 4) {
156                                         if (width > i + 3) numxpixels = 4;
157                                         else numxpixels = width - i;
158                                         encode_block(blkaddr, srcaddr, width, numxpixels, numypixels, -1);
159                                         srcaddr += 4 * numxpixels;
160                                         blkaddr += 8;
161                                 }
162                                 blkaddr += dstRowDiff;
163                         }
164                         break;
165                 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
166                         dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) & ~3) * 4) : 0;
167                         /*      fprintf(stderr, "dxt3 tex width %d tex height %d dstRowStride %d\n",
168                                 width, height, dstRowStride); */
169                         encode_block = s2tc_encode_block_func(DXT3, WAVG, -1);
170                         for (j = 0; j < height; j += 4) {
171                                 if (height > j + 3) numypixels = 4;
172                                 else numypixels = height - j;
173                                 srcaddr = rgba + j * width * 4;
174                                 for (i = 0; i < width; i += 4) {
175                                         if (width > i + 3) numxpixels = 4;
176                                         else numxpixels = width - i;
177                                         encode_block(blkaddr, srcaddr, width, numxpixels, numypixels, -1);
178                                         srcaddr += 4 * numxpixels;
179                                         blkaddr += 16;
180                                 }
181                                 blkaddr += dstRowDiff;
182                         }
183                         break;
184                 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
185                         dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) & ~3) * 4) : 0;
186                         /*      fprintf(stderr, "dxt5 tex width %d tex height %d dstRowStride %d\n",
187                                 width, height, dstRowStride); */
188                         encode_block = s2tc_encode_block_func(DXT5, WAVG, -1);
189                         for (j = 0; j < height; j += 4) {
190                                 if (height > j + 3) numypixels = 4;
191                                 else numypixels = height - j;
192                                 srcaddr = rgba + j * width * 4;
193                                 for (i = 0; i < width; i += 4) {
194                                         if (width > i + 3) numxpixels = 4;
195                                         else numxpixels = width - i;
196                                         encode_block(blkaddr, srcaddr, width, numxpixels, numypixels, -1);
197                                         srcaddr += 4 * numxpixels;
198                                         blkaddr += 16;
199                                 }
200                                 blkaddr += dstRowDiff;
201                         }
202                         break;
203         }
204
205         free(rgba);
206 }