mesa: Remove commented-out DXTn fetch code
[mesa.git] / src / mesa / main / texcompress_s3tc_tmp.h
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 #ifdef __APPLE__
26 #include <OpenGL/gl.h>
27 #else
28 #include <GL/gl.h>
29 #endif
30
31 typedef GLubyte GLchan;
32 #define UBYTE_TO_CHAN(b) (b)
33 #define CHAN_MAX 255
34 #define RCOMP 0
35 #define GCOMP 1
36 #define BCOMP 2
37 #define ACOMP 3
38
39 void fetch_2d_texel_rgb_dxt1(GLint srcRowStride, const GLubyte *pixdata,
40 GLint i, GLint j, GLvoid *texel);
41 void fetch_2d_texel_rgba_dxt1(GLint srcRowStride, const GLubyte *pixdata,
42 GLint i, GLint j, GLvoid *texel);
43 void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata,
44 GLint i, GLint j, GLvoid *texel);
45 void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata,
46 GLint i, GLint j, GLvoid *texel);
47
48 void tx_compress_dxtn(GLint srccomps, GLint width, GLint height,
49 const GLubyte *srcPixData, GLenum destformat,
50 GLubyte *dest, GLint dstRowStride);
51
52 #define EXP5TO8R(packedcol) \
53 ((((packedcol) >> 8) & 0xf8) | (((packedcol) >> 13) & 0x7))
54
55 #define EXP6TO8G(packedcol) \
56 ((((packedcol) >> 3) & 0xfc) | (((packedcol) >> 9) & 0x3))
57
58 #define EXP5TO8B(packedcol) \
59 ((((packedcol) << 3) & 0xf8) | (((packedcol) >> 2) & 0x7))
60
61 #define EXP4TO8(col) \
62 ((col) | ((col) << 4))
63
64 /* inefficient. To be efficient, it would be necessary to decode 16 pixels at once */
65
66 static void dxt135_decode_imageblock ( const GLubyte *img_block_src,
67 GLint i, GLint j, GLuint dxt_type, GLvoid *texel ) {
68 GLchan *rgba = (GLchan *) texel;
69 const GLushort color0 = img_block_src[0] | (img_block_src[1] << 8);
70 const GLushort color1 = img_block_src[2] | (img_block_src[3] << 8);
71 const GLuint bits = img_block_src[4] | (img_block_src[5] << 8) |
72 (img_block_src[6] << 16) | (img_block_src[7] << 24);
73 /* What about big/little endian? */
74 GLubyte bit_pos = 2 * (j * 4 + i) ;
75 GLubyte code = (GLubyte) ((bits >> bit_pos) & 3);
76
77 rgba[ACOMP] = CHAN_MAX;
78 switch (code) {
79 case 0:
80 rgba[RCOMP] = UBYTE_TO_CHAN( EXP5TO8R(color0) );
81 rgba[GCOMP] = UBYTE_TO_CHAN( EXP6TO8G(color0) );
82 rgba[BCOMP] = UBYTE_TO_CHAN( EXP5TO8B(color0) );
83 break;
84 case 1:
85 rgba[RCOMP] = UBYTE_TO_CHAN( EXP5TO8R(color1) );
86 rgba[GCOMP] = UBYTE_TO_CHAN( EXP6TO8G(color1) );
87 rgba[BCOMP] = UBYTE_TO_CHAN( EXP5TO8B(color1) );
88 break;
89 case 2:
90 if ((dxt_type > 1) || (color0 > color1)) {
91 rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) * 2 + EXP5TO8R(color1)) / 3) );
92 rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) * 2 + EXP6TO8G(color1)) / 3) );
93 rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) * 2 + EXP5TO8B(color1)) / 3) );
94 }
95 else {
96 rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) + EXP5TO8R(color1)) / 2) );
97 rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) + EXP6TO8G(color1)) / 2) );
98 rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) + EXP5TO8B(color1)) / 2) );
99 }
100 break;
101 case 3:
102 if ((dxt_type > 1) || (color0 > color1)) {
103 rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) + EXP5TO8R(color1) * 2) / 3) );
104 rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) + EXP6TO8G(color1) * 2) / 3) );
105 rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) + EXP5TO8B(color1) * 2) / 3) );
106 }
107 else {
108 rgba[RCOMP] = 0;
109 rgba[GCOMP] = 0;
110 rgba[BCOMP] = 0;
111 if (dxt_type == 1) rgba[ACOMP] = UBYTE_TO_CHAN(0);
112 }
113 break;
114 default:
115 /* CANNOT happen (I hope) */
116 break;
117 }
118 }
119
120
121 void fetch_2d_texel_rgb_dxt1(GLint srcRowStride, const GLubyte *pixdata,
122 GLint i, GLint j, GLvoid *texel)
123 {
124 /* Extract the (i,j) pixel from pixdata and return it
125 * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP].
126 */
127
128 const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
129 dxt135_decode_imageblock(blksrc, (i&3), (j&3), 0, texel);
130 }
131
132
133 void fetch_2d_texel_rgba_dxt1(GLint srcRowStride, const GLubyte *pixdata,
134 GLint i, GLint j, GLvoid *texel)
135 {
136 /* Extract the (i,j) pixel from pixdata and return it
137 * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP].
138 */
139
140 const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8);
141 dxt135_decode_imageblock(blksrc, (i&3), (j&3), 1, texel);
142 }
143
144 void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata,
145 GLint i, GLint j, GLvoid *texel) {
146
147 /* Extract the (i,j) pixel from pixdata and return it
148 * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP].
149 */
150
151 GLchan *rgba = (GLchan *) texel;
152 const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16);
153 const GLubyte anibble = (blksrc[((j&3) * 4 + (i&3)) / 2] >> (4 * (i&1))) & 0xf;
154 dxt135_decode_imageblock(blksrc + 8, (i&3), (j&3), 2, texel);
155 rgba[ACOMP] = UBYTE_TO_CHAN( (GLubyte)(EXP4TO8(anibble)) );
156 }
157
158 void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata,
159 GLint i, GLint j, GLvoid *texel) {
160
161 /* Extract the (i,j) pixel from pixdata and return it
162 * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP].
163 */
164
165 GLchan *rgba = (GLchan *) texel;
166 const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16);
167 const GLubyte alpha0 = blksrc[0];
168 const GLubyte alpha1 = blksrc[1];
169 const GLubyte bit_pos = ((j&3) * 4 + (i&3)) * 3;
170 const GLubyte acodelow = blksrc[2 + bit_pos / 8];
171 const GLubyte acodehigh = blksrc[3 + bit_pos / 8];
172 const GLubyte code = (acodelow >> (bit_pos & 0x7) |
173 (acodehigh << (8 - (bit_pos & 0x7)))) & 0x7;
174 dxt135_decode_imageblock(blksrc + 8, (i&3), (j&3), 2, texel);
175 if (code == 0)
176 rgba[ACOMP] = UBYTE_TO_CHAN( alpha0 );
177 else if (code == 1)
178 rgba[ACOMP] = UBYTE_TO_CHAN( alpha1 );
179 else if (alpha0 > alpha1)
180 rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (8 - code) + (alpha1 * (code - 1))) / 7) );
181 else if (code < 6)
182 rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (6 - code) + (alpha1 * (code - 1))) / 5) );
183 else if (code == 6)
184 rgba[ACOMP] = 0;
185 else
186 rgba[ACOMP] = CHAN_MAX;
187 }
188
189
190 /* weights used for error function, basically weights (unsquared 2/4/1) according to rgb->luminance conversion
191 not sure if this really reflects visual perception */
192 #define REDWEIGHT 4
193 #define GREENWEIGHT 16
194 #define BLUEWEIGHT 1
195
196 #define ALPHACUT 127
197
198 static void fancybasecolorsearch( GLubyte *blkaddr, GLubyte srccolors[4][4][4], GLubyte *bestcolor[2],
199 GLint numxpixels, GLint numypixels, GLint type, GLboolean haveAlpha)
200 {
201 /* use same luminance-weighted distance metric to determine encoding as for finding the base colors */
202
203 /* TODO could also try to find a better encoding for the 3-color-encoding type, this really should be done
204 if it's rgba_dxt1 and we have alpha in the block, currently even values which will be mapped to black
205 due to their alpha value will influence the result */
206 GLint i, j, colors, z;
207 GLuint pixerror, pixerrorred, pixerrorgreen, pixerrorblue, pixerrorbest;
208 GLint colordist, blockerrlin[2][3];
209 GLubyte nrcolor[2];
210 GLint pixerrorcolorbest[3];
211 GLubyte enc = 0;
212 GLubyte cv[4][4];
213 GLubyte testcolor[2][3];
214
215 /* fprintf(stderr, "color begin 0 r/g/b %d/%d/%d, 1 r/g/b %d/%d/%d\n",
216 bestcolor[0][0], bestcolor[0][1], bestcolor[0][2], bestcolor[1][0], bestcolor[1][1], bestcolor[1][2]);*/
217 if (((bestcolor[0][0] & 0xf8) << 8 | (bestcolor[0][1] & 0xfc) << 3 | bestcolor[0][2] >> 3) <
218 ((bestcolor[1][0] & 0xf8) << 8 | (bestcolor[1][1] & 0xfc) << 3 | bestcolor[1][2] >> 3)) {
219 testcolor[0][0] = bestcolor[0][0];
220 testcolor[0][1] = bestcolor[0][1];
221 testcolor[0][2] = bestcolor[0][2];
222 testcolor[1][0] = bestcolor[1][0];
223 testcolor[1][1] = bestcolor[1][1];
224 testcolor[1][2] = bestcolor[1][2];
225 }
226 else {
227 testcolor[1][0] = bestcolor[0][0];
228 testcolor[1][1] = bestcolor[0][1];
229 testcolor[1][2] = bestcolor[0][2];
230 testcolor[0][0] = bestcolor[1][0];
231 testcolor[0][1] = bestcolor[1][1];
232 testcolor[0][2] = bestcolor[1][2];
233 }
234
235 for (i = 0; i < 3; i ++) {
236 cv[0][i] = testcolor[0][i];
237 cv[1][i] = testcolor[1][i];
238 cv[2][i] = (testcolor[0][i] * 2 + testcolor[1][i]) / 3;
239 cv[3][i] = (testcolor[0][i] + testcolor[1][i] * 2) / 3;
240 }
241
242 blockerrlin[0][0] = 0;
243 blockerrlin[0][1] = 0;
244 blockerrlin[0][2] = 0;
245 blockerrlin[1][0] = 0;
246 blockerrlin[1][1] = 0;
247 blockerrlin[1][2] = 0;
248
249 nrcolor[0] = 0;
250 nrcolor[1] = 0;
251
252 for (j = 0; j < numypixels; j++) {
253 for (i = 0; i < numxpixels; i++) {
254 pixerrorbest = 0xffffffff;
255 for (colors = 0; colors < 4; colors++) {
256 colordist = srccolors[j][i][0] - (cv[colors][0]);
257 pixerror = colordist * colordist * REDWEIGHT;
258 pixerrorred = colordist;
259 colordist = srccolors[j][i][1] - (cv[colors][1]);
260 pixerror += colordist * colordist * GREENWEIGHT;
261 pixerrorgreen = colordist;
262 colordist = srccolors[j][i][2] - (cv[colors][2]);
263 pixerror += colordist * colordist * BLUEWEIGHT;
264 pixerrorblue = colordist;
265 if (pixerror < pixerrorbest) {
266 enc = colors;
267 pixerrorbest = pixerror;
268 pixerrorcolorbest[0] = pixerrorred;
269 pixerrorcolorbest[1] = pixerrorgreen;
270 pixerrorcolorbest[2] = pixerrorblue;
271 }
272 }
273 if (enc == 0) {
274 for (z = 0; z < 3; z++) {
275 blockerrlin[0][z] += 3 * pixerrorcolorbest[z];
276 }
277 nrcolor[0] += 3;
278 }
279 else if (enc == 2) {
280 for (z = 0; z < 3; z++) {
281 blockerrlin[0][z] += 2 * pixerrorcolorbest[z];
282 }
283 nrcolor[0] += 2;
284 for (z = 0; z < 3; z++) {
285 blockerrlin[1][z] += 1 * pixerrorcolorbest[z];
286 }
287 nrcolor[1] += 1;
288 }
289 else if (enc == 3) {
290 for (z = 0; z < 3; z++) {
291 blockerrlin[0][z] += 1 * pixerrorcolorbest[z];
292 }
293 nrcolor[0] += 1;
294 for (z = 0; z < 3; z++) {
295 blockerrlin[1][z] += 2 * pixerrorcolorbest[z];
296 }
297 nrcolor[1] += 2;
298 }
299 else if (enc == 1) {
300 for (z = 0; z < 3; z++) {
301 blockerrlin[1][z] += 3 * pixerrorcolorbest[z];
302 }
303 nrcolor[1] += 3;
304 }
305 }
306 }
307 if (nrcolor[0] == 0) nrcolor[0] = 1;
308 if (nrcolor[1] == 0) nrcolor[1] = 1;
309 for (j = 0; j < 2; j++) {
310 for (i = 0; i < 3; i++) {
311 GLint newvalue = testcolor[j][i] + blockerrlin[j][i] / nrcolor[j];
312 if (newvalue <= 0)
313 testcolor[j][i] = 0;
314 else if (newvalue >= 255)
315 testcolor[j][i] = 255;
316 else testcolor[j][i] = newvalue;
317 }
318 }
319
320 if ((abs(testcolor[0][0] - testcolor[1][0]) < 8) &&
321 (abs(testcolor[0][1] - testcolor[1][1]) < 4) &&
322 (abs(testcolor[0][2] - testcolor[1][2]) < 8)) {
323 /* both colors are so close they might get encoded as the same 16bit values */
324 GLubyte coldiffred, coldiffgreen, coldiffblue, coldiffmax, factor, ind0, ind1;
325
326 coldiffred = abs(testcolor[0][0] - testcolor[1][0]);
327 coldiffgreen = 2 * abs(testcolor[0][1] - testcolor[1][1]);
328 coldiffblue = abs(testcolor[0][2] - testcolor[1][2]);
329 coldiffmax = coldiffred;
330 if (coldiffmax < coldiffgreen) coldiffmax = coldiffgreen;
331 if (coldiffmax < coldiffblue) coldiffmax = coldiffblue;
332 if (coldiffmax > 0) {
333 if (coldiffmax > 4) factor = 2;
334 else if (coldiffmax > 2) factor = 3;
335 else factor = 4;
336 /* Won't do much if the color value is near 255... */
337 /* argh so many ifs */
338 if (testcolor[1][1] >= testcolor[0][1]) {
339 ind1 = 1; ind0 = 0;
340 }
341 else {
342 ind1 = 0; ind0 = 1;
343 }
344 if ((testcolor[ind1][1] + factor * coldiffgreen) <= 255)
345 testcolor[ind1][1] += factor * coldiffgreen;
346 else testcolor[ind1][1] = 255;
347 if ((testcolor[ind1][0] - testcolor[ind0][1]) > 0) {
348 if ((testcolor[ind1][0] + factor * coldiffred) <= 255)
349 testcolor[ind1][0] += factor * coldiffred;
350 else testcolor[ind1][0] = 255;
351 }
352 else {
353 if ((testcolor[ind0][0] + factor * coldiffred) <= 255)
354 testcolor[ind0][0] += factor * coldiffred;
355 else testcolor[ind0][0] = 255;
356 }
357 if ((testcolor[ind1][2] - testcolor[ind0][2]) > 0) {
358 if ((testcolor[ind1][2] + factor * coldiffblue) <= 255)
359 testcolor[ind1][2] += factor * coldiffblue;
360 else testcolor[ind1][2] = 255;
361 }
362 else {
363 if ((testcolor[ind0][2] + factor * coldiffblue) <= 255)
364 testcolor[ind0][2] += factor * coldiffblue;
365 else testcolor[ind0][2] = 255;
366 }
367 }
368 }
369
370 if (((testcolor[0][0] & 0xf8) << 8 | (testcolor[0][1] & 0xfc) << 3 | testcolor[0][2] >> 3) <
371 ((testcolor[1][0] & 0xf8) << 8 | (testcolor[1][1] & 0xfc) << 3 | testcolor[1][2]) >> 3) {
372 for (i = 0; i < 3; i++) {
373 bestcolor[0][i] = testcolor[0][i];
374 bestcolor[1][i] = testcolor[1][i];
375 }
376 }
377 else {
378 for (i = 0; i < 3; i++) {
379 bestcolor[0][i] = testcolor[1][i];
380 bestcolor[1][i] = testcolor[0][i];
381 }
382 }
383
384 /* fprintf(stderr, "color end 0 r/g/b %d/%d/%d, 1 r/g/b %d/%d/%d\n",
385 bestcolor[0][0], bestcolor[0][1], bestcolor[0][2], bestcolor[1][0], bestcolor[1][1], bestcolor[1][2]);*/
386 }
387
388
389
390 static void storedxtencodedblock( GLubyte *blkaddr, GLubyte srccolors[4][4][4], GLubyte *bestcolor[2],
391 GLint numxpixels, GLint numypixels, GLuint type, GLboolean haveAlpha)
392 {
393 /* use same luminance-weighted distance metric to determine encoding as for finding the base colors */
394
395 GLint i, j, colors;
396 GLuint testerror, testerror2, pixerror, pixerrorbest;
397 GLint colordist;
398 GLushort color0, color1, tempcolor;
399 GLuint bits = 0, bits2 = 0;
400 GLubyte *colorptr;
401 GLubyte enc = 0;
402 GLubyte cv[4][4];
403
404 bestcolor[0][0] = bestcolor[0][0] & 0xf8;
405 bestcolor[0][1] = bestcolor[0][1] & 0xfc;
406 bestcolor[0][2] = bestcolor[0][2] & 0xf8;
407 bestcolor[1][0] = bestcolor[1][0] & 0xf8;
408 bestcolor[1][1] = bestcolor[1][1] & 0xfc;
409 bestcolor[1][2] = bestcolor[1][2] & 0xf8;
410
411 color0 = bestcolor[0][0] << 8 | bestcolor[0][1] << 3 | bestcolor[0][2] >> 3;
412 color1 = bestcolor[1][0] << 8 | bestcolor[1][1] << 3 | bestcolor[1][2] >> 3;
413 if (color0 < color1) {
414 tempcolor = color0; color0 = color1; color1 = tempcolor;
415 colorptr = bestcolor[0]; bestcolor[0] = bestcolor[1]; bestcolor[1] = colorptr;
416 }
417
418
419 for (i = 0; i < 3; i++) {
420 cv[0][i] = bestcolor[0][i];
421 cv[1][i] = bestcolor[1][i];
422 cv[2][i] = (bestcolor[0][i] * 2 + bestcolor[1][i]) / 3;
423 cv[3][i] = (bestcolor[0][i] + bestcolor[1][i] * 2) / 3;
424 }
425
426 testerror = 0;
427 for (j = 0; j < numypixels; j++) {
428 for (i = 0; i < numxpixels; i++) {
429 pixerrorbest = 0xffffffff;
430 for (colors = 0; colors < 4; colors++) {
431 colordist = srccolors[j][i][0] - cv[colors][0];
432 pixerror = colordist * colordist * REDWEIGHT;
433 colordist = srccolors[j][i][1] - cv[colors][1];
434 pixerror += colordist * colordist * GREENWEIGHT;
435 colordist = srccolors[j][i][2] - cv[colors][2];
436 pixerror += colordist * colordist * BLUEWEIGHT;
437 if (pixerror < pixerrorbest) {
438 pixerrorbest = pixerror;
439 enc = colors;
440 }
441 }
442 testerror += pixerrorbest;
443 bits |= enc << (2 * (j * 4 + i));
444 }
445 }
446 /* some hw might disagree but actually decoding should always use 4-color encoding
447 for non-dxt1 formats */
448 if (type == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || type == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
449 for (i = 0; i < 3; i++) {
450 cv[2][i] = (bestcolor[0][i] + bestcolor[1][i]) / 2;
451 /* this isn't used. Looks like the black color constant can only be used
452 with RGB_DXT1 if I read the spec correctly (note though that the radeon gpu disagrees,
453 it will decode 3 to black even with DXT3/5), and due to how the color searching works
454 it won't get used even then */
455 cv[3][i] = 0;
456 }
457 testerror2 = 0;
458 for (j = 0; j < numypixels; j++) {
459 for (i = 0; i < numxpixels; i++) {
460 pixerrorbest = 0xffffffff;
461 if ((type == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) && (srccolors[j][i][3] <= ALPHACUT)) {
462 enc = 3;
463 pixerrorbest = 0; /* don't calculate error */
464 }
465 else {
466 /* we're calculating the same what we have done already for colors 0-1 above... */
467 for (colors = 0; colors < 3; colors++) {
468 colordist = srccolors[j][i][0] - cv[colors][0];
469 pixerror = colordist * colordist * REDWEIGHT;
470 colordist = srccolors[j][i][1] - cv[colors][1];
471 pixerror += colordist * colordist * GREENWEIGHT;
472 colordist = srccolors[j][i][2] - cv[colors][2];
473 pixerror += colordist * colordist * BLUEWEIGHT;
474 if (pixerror < pixerrorbest) {
475 pixerrorbest = pixerror;
476 /* need to exchange colors later */
477 if (colors > 1) enc = colors;
478 else enc = colors ^ 1;
479 }
480 }
481 }
482 testerror2 += pixerrorbest;
483 bits2 |= enc << (2 * (j * 4 + i));
484 }
485 }
486 } else {
487 testerror2 = 0xffffffff;
488 }
489
490 /* finally we're finished, write back colors and bits */
491 if ((testerror > testerror2) || (haveAlpha)) {
492 *blkaddr++ = color1 & 0xff;
493 *blkaddr++ = color1 >> 8;
494 *blkaddr++ = color0 & 0xff;
495 *blkaddr++ = color0 >> 8;
496 *blkaddr++ = bits2 & 0xff;
497 *blkaddr++ = ( bits2 >> 8) & 0xff;
498 *blkaddr++ = ( bits2 >> 16) & 0xff;
499 *blkaddr = bits2 >> 24;
500 }
501 else {
502 *blkaddr++ = color0 & 0xff;
503 *blkaddr++ = color0 >> 8;
504 *blkaddr++ = color1 & 0xff;
505 *blkaddr++ = color1 >> 8;
506 *blkaddr++ = bits & 0xff;
507 *blkaddr++ = ( bits >> 8) & 0xff;
508 *blkaddr++ = ( bits >> 16) & 0xff;
509 *blkaddr = bits >> 24;
510 }
511 }
512
513 static void encodedxtcolorblockfaster( GLubyte *blkaddr, GLubyte srccolors[4][4][4],
514 GLint numxpixels, GLint numypixels, GLuint type )
515 {
516 /* simplistic approach. We need two base colors, simply use the "highest" and the "lowest" color
517 present in the picture as base colors */
518
519 /* define lowest and highest color as shortest and longest vector to 0/0/0, though the
520 vectors are weighted similar to their importance in rgb-luminance conversion
521 doesn't work too well though...
522 This seems to be a rather difficult problem */
523
524 GLubyte *bestcolor[2];
525 GLubyte basecolors[2][3];
526 GLubyte i, j;
527 GLuint lowcv, highcv, testcv;
528 GLboolean haveAlpha = GL_FALSE;
529
530 lowcv = highcv = srccolors[0][0][0] * srccolors[0][0][0] * REDWEIGHT +
531 srccolors[0][0][1] * srccolors[0][0][1] * GREENWEIGHT +
532 srccolors[0][0][2] * srccolors[0][0][2] * BLUEWEIGHT;
533 bestcolor[0] = bestcolor[1] = srccolors[0][0];
534 for (j = 0; j < numypixels; j++) {
535 for (i = 0; i < numxpixels; i++) {
536 /* don't use this as a base color if the pixel will get black/transparent anyway */
537 if ((type != GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) || (srccolors[j][i][3] > ALPHACUT)) {
538 testcv = srccolors[j][i][0] * srccolors[j][i][0] * REDWEIGHT +
539 srccolors[j][i][1] * srccolors[j][i][1] * GREENWEIGHT +
540 srccolors[j][i][2] * srccolors[j][i][2] * BLUEWEIGHT;
541 if (testcv > highcv) {
542 highcv = testcv;
543 bestcolor[1] = srccolors[j][i];
544 }
545 else if (testcv < lowcv) {
546 lowcv = testcv;
547 bestcolor[0] = srccolors[j][i];
548 }
549 }
550 else haveAlpha = GL_TRUE;
551 }
552 }
553 /* make sure the original color values won't get touched... */
554 for (j = 0; j < 2; j++) {
555 for (i = 0; i < 3; i++) {
556 basecolors[j][i] = bestcolor[j][i];
557 }
558 }
559 bestcolor[0] = basecolors[0];
560 bestcolor[1] = basecolors[1];
561
562 /* try to find better base colors */
563 fancybasecolorsearch(blkaddr, srccolors, bestcolor, numxpixels, numypixels, type, haveAlpha);
564 /* find the best encoding for these colors, and store the result */
565 storedxtencodedblock(blkaddr, srccolors, bestcolor, numxpixels, numypixels, type, haveAlpha);
566 }
567
568 static void writedxt5encodedalphablock( GLubyte *blkaddr, GLubyte alphabase1, GLubyte alphabase2,
569 GLubyte alphaenc[16])
570 {
571 *blkaddr++ = alphabase1;
572 *blkaddr++ = alphabase2;
573 *blkaddr++ = alphaenc[0] | (alphaenc[1] << 3) | ((alphaenc[2] & 3) << 6);
574 *blkaddr++ = (alphaenc[2] >> 2) | (alphaenc[3] << 1) | (alphaenc[4] << 4) | ((alphaenc[5] & 1) << 7);
575 *blkaddr++ = (alphaenc[5] >> 1) | (alphaenc[6] << 2) | (alphaenc[7] << 5);
576 *blkaddr++ = alphaenc[8] | (alphaenc[9] << 3) | ((alphaenc[10] & 3) << 6);
577 *blkaddr++ = (alphaenc[10] >> 2) | (alphaenc[11] << 1) | (alphaenc[12] << 4) | ((alphaenc[13] & 1) << 7);
578 *blkaddr++ = (alphaenc[13] >> 1) | (alphaenc[14] << 2) | (alphaenc[15] << 5);
579 }
580
581 static void encodedxt5alpha(GLubyte *blkaddr, GLubyte srccolors[4][4][4],
582 GLint numxpixels, GLint numypixels)
583 {
584 GLubyte alphabase[2], alphause[2];
585 GLshort alphatest[2];
586 GLuint alphablockerror1, alphablockerror2, alphablockerror3;
587 GLubyte i, j, aindex, acutValues[7];
588 GLubyte alphaenc1[16], alphaenc2[16], alphaenc3[16];
589 GLboolean alphaabsmin = GL_FALSE;
590 GLboolean alphaabsmax = GL_FALSE;
591 GLshort alphadist;
592
593 /* find lowest and highest alpha value in block, alphabase[0] lowest, alphabase[1] highest */
594 alphabase[0] = 0xff; alphabase[1] = 0x0;
595 for (j = 0; j < numypixels; j++) {
596 for (i = 0; i < numxpixels; i++) {
597 if (srccolors[j][i][3] == 0)
598 alphaabsmin = GL_TRUE;
599 else if (srccolors[j][i][3] == 255)
600 alphaabsmax = GL_TRUE;
601 else {
602 if (srccolors[j][i][3] > alphabase[1])
603 alphabase[1] = srccolors[j][i][3];
604 if (srccolors[j][i][3] < alphabase[0])
605 alphabase[0] = srccolors[j][i][3];
606 }
607 }
608 }
609
610
611 if ((alphabase[0] > alphabase[1]) && !(alphaabsmin && alphaabsmax)) { /* one color, either max or min */
612 /* shortcut here since it is a very common case (and also avoids later problems) */
613 /* || (alphabase[0] == alphabase[1] && !alphaabsmin && !alphaabsmax) */
614 /* could also thest for alpha0 == alpha1 (and not min/max), but probably not common, so don't bother */
615
616 *blkaddr++ = srccolors[0][0][3];
617 blkaddr++;
618 *blkaddr++ = 0;
619 *blkaddr++ = 0;
620 *blkaddr++ = 0;
621 *blkaddr++ = 0;
622 *blkaddr++ = 0;
623 *blkaddr++ = 0;
624 /* fprintf(stderr, "enc0 used\n");*/
625 return;
626 }
627
628 /* find best encoding for alpha0 > alpha1 */
629 /* it's possible this encoding is better even if both alphaabsmin and alphaabsmax are true */
630 alphablockerror1 = 0x0;
631 alphablockerror2 = 0xffffffff;
632 alphablockerror3 = 0xffffffff;
633 if (alphaabsmin) alphause[0] = 0;
634 else alphause[0] = alphabase[0];
635 if (alphaabsmax) alphause[1] = 255;
636 else alphause[1] = alphabase[1];
637 /* calculate the 7 cut values, just the middle between 2 of the computed alpha values */
638 for (aindex = 0; aindex < 7; aindex++) {
639 /* don't forget here is always rounded down */
640 acutValues[aindex] = (alphause[0] * (2*aindex + 1) + alphause[1] * (14 - (2*aindex + 1))) / 14;
641 }
642
643 for (j = 0; j < numypixels; j++) {
644 for (i = 0; i < numxpixels; i++) {
645 /* maybe it's overkill to have the most complicated calculation just for the error
646 calculation which we only need to figure out if encoding1 or encoding2 is better... */
647 if (srccolors[j][i][3] > acutValues[0]) {
648 alphaenc1[4*j + i] = 0;
649 alphadist = srccolors[j][i][3] - alphause[1];
650 }
651 else if (srccolors[j][i][3] > acutValues[1]) {
652 alphaenc1[4*j + i] = 2;
653 alphadist = srccolors[j][i][3] - (alphause[1] * 6 + alphause[0] * 1) / 7;
654 }
655 else if (srccolors[j][i][3] > acutValues[2]) {
656 alphaenc1[4*j + i] = 3;
657 alphadist = srccolors[j][i][3] - (alphause[1] * 5 + alphause[0] * 2) / 7;
658 }
659 else if (srccolors[j][i][3] > acutValues[3]) {
660 alphaenc1[4*j + i] = 4;
661 alphadist = srccolors[j][i][3] - (alphause[1] * 4 + alphause[0] * 3) / 7;
662 }
663 else if (srccolors[j][i][3] > acutValues[4]) {
664 alphaenc1[4*j + i] = 5;
665 alphadist = srccolors[j][i][3] - (alphause[1] * 3 + alphause[0] * 4) / 7;
666 }
667 else if (srccolors[j][i][3] > acutValues[5]) {
668 alphaenc1[4*j + i] = 6;
669 alphadist = srccolors[j][i][3] - (alphause[1] * 2 + alphause[0] * 5) / 7;
670 }
671 else if (srccolors[j][i][3] > acutValues[6]) {
672 alphaenc1[4*j + i] = 7;
673 alphadist = srccolors[j][i][3] - (alphause[1] * 1 + alphause[0] * 6) / 7;
674 }
675 else {
676 alphaenc1[4*j + i] = 1;
677 alphadist = srccolors[j][i][3] - alphause[0];
678 }
679 alphablockerror1 += alphadist * alphadist;
680 }
681 }
682 /* for (i = 0; i < 16; i++) {
683 fprintf(stderr, "%d ", alphaenc1[i]);
684 }
685 fprintf(stderr, "cutVals ");
686 for (i = 0; i < 8; i++) {
687 fprintf(stderr, "%d ", acutValues[i]);
688 }
689 fprintf(stderr, "srcVals ");
690 for (j = 0; j < numypixels; j++)
691 for (i = 0; i < numxpixels; i++) {
692 fprintf(stderr, "%d ", srccolors[j][i][3]);
693 }
694
695 fprintf(stderr, "\n");
696 }*/
697 /* it's not very likely this encoding is better if both alphaabsmin and alphaabsmax
698 are false but try it anyway */
699 if (alphablockerror1 >= 32) {
700
701 /* don't bother if encoding is already very good, this condition should also imply
702 we have valid alphabase colors which we absolutely need (alphabase[0] <= alphabase[1]) */
703 alphablockerror2 = 0;
704 for (aindex = 0; aindex < 5; aindex++) {
705 /* don't forget here is always rounded down */
706 acutValues[aindex] = (alphabase[0] * (10 - (2*aindex + 1)) + alphabase[1] * (2*aindex + 1)) / 10;
707 }
708 for (j = 0; j < numypixels; j++) {
709 for (i = 0; i < numxpixels; i++) {
710 /* maybe it's overkill to have the most complicated calculation just for the error
711 calculation which we only need to figure out if encoding1 or encoding2 is better... */
712 if (srccolors[j][i][3] == 0) {
713 alphaenc2[4*j + i] = 6;
714 alphadist = 0;
715 }
716 else if (srccolors[j][i][3] == 255) {
717 alphaenc2[4*j + i] = 7;
718 alphadist = 0;
719 }
720 else if (srccolors[j][i][3] <= acutValues[0]) {
721 alphaenc2[4*j + i] = 0;
722 alphadist = srccolors[j][i][3] - alphabase[0];
723 }
724 else if (srccolors[j][i][3] <= acutValues[1]) {
725 alphaenc2[4*j + i] = 2;
726 alphadist = srccolors[j][i][3] - (alphabase[0] * 4 + alphabase[1] * 1) / 5;
727 }
728 else if (srccolors[j][i][3] <= acutValues[2]) {
729 alphaenc2[4*j + i] = 3;
730 alphadist = srccolors[j][i][3] - (alphabase[0] * 3 + alphabase[1] * 2) / 5;
731 }
732 else if (srccolors[j][i][3] <= acutValues[3]) {
733 alphaenc2[4*j + i] = 4;
734 alphadist = srccolors[j][i][3] - (alphabase[0] * 2 + alphabase[1] * 3) / 5;
735 }
736 else if (srccolors[j][i][3] <= acutValues[4]) {
737 alphaenc2[4*j + i] = 5;
738 alphadist = srccolors[j][i][3] - (alphabase[0] * 1 + alphabase[1] * 4) / 5;
739 }
740 else {
741 alphaenc2[4*j + i] = 1;
742 alphadist = srccolors[j][i][3] - alphabase[1];
743 }
744 alphablockerror2 += alphadist * alphadist;
745 }
746 }
747
748
749 /* skip this if the error is already very small
750 this encoding is MUCH better on average than #2 though, but expensive! */
751 if ((alphablockerror2 > 96) && (alphablockerror1 > 96)) {
752 GLshort blockerrlin1 = 0;
753 GLshort blockerrlin2 = 0;
754 GLubyte nralphainrangelow = 0;
755 GLubyte nralphainrangehigh = 0;
756 alphatest[0] = 0xff;
757 alphatest[1] = 0x0;
758 /* if we have large range it's likely there are values close to 0/255, try to map them to 0/255 */
759 for (j = 0; j < numypixels; j++) {
760 for (i = 0; i < numxpixels; i++) {
761 if ((srccolors[j][i][3] > alphatest[1]) && (srccolors[j][i][3] < (255 -(alphabase[1] - alphabase[0]) / 28)))
762 alphatest[1] = srccolors[j][i][3];
763 if ((srccolors[j][i][3] < alphatest[0]) && (srccolors[j][i][3] > (alphabase[1] - alphabase[0]) / 28))
764 alphatest[0] = srccolors[j][i][3];
765 }
766 }
767 /* shouldn't happen too often, don't really care about those degenerated cases */
768 if (alphatest[1] <= alphatest[0]) {
769 alphatest[0] = 1;
770 alphatest[1] = 254;
771 /* fprintf(stderr, "only 1 or 0 colors for encoding!\n");*/
772 }
773 for (aindex = 0; aindex < 5; aindex++) {
774 /* don't forget here is always rounded down */
775 acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
776 }
777
778 /* find the "average" difference between the alpha values and the next encoded value.
779 This is then used to calculate new base values.
780 Should there be some weighting, i.e. those values closer to alphatest[x] have more weight,
781 since they will see more improvement, and also because the values in the middle are somewhat
782 likely to get no improvement at all (because the base values might move in different directions)?
783 OTOH it would mean the values in the middle are even less likely to get an improvement
784 */
785 for (j = 0; j < numypixels; j++) {
786 for (i = 0; i < numxpixels; i++) {
787 if (srccolors[j][i][3] <= alphatest[0] / 2) {
788 }
789 else if (srccolors[j][i][3] > ((255 + alphatest[1]) / 2)) {
790 }
791 else if (srccolors[j][i][3] <= acutValues[0]) {
792 blockerrlin1 += (srccolors[j][i][3] - alphatest[0]);
793 nralphainrangelow += 1;
794 }
795 else if (srccolors[j][i][3] <= acutValues[1]) {
796 blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
797 blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
798 nralphainrangelow += 1;
799 nralphainrangehigh += 1;
800 }
801 else if (srccolors[j][i][3] <= acutValues[2]) {
802 blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
803 blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
804 nralphainrangelow += 1;
805 nralphainrangehigh += 1;
806 }
807 else if (srccolors[j][i][3] <= acutValues[3]) {
808 blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
809 blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
810 nralphainrangelow += 1;
811 nralphainrangehigh += 1;
812 }
813 else if (srccolors[j][i][3] <= acutValues[4]) {
814 blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
815 blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
816 nralphainrangelow += 1;
817 nralphainrangehigh += 1;
818 }
819 else {
820 blockerrlin2 += (srccolors[j][i][3] - alphatest[1]);
821 nralphainrangehigh += 1;
822 }
823 }
824 }
825 /* shouldn't happen often, needed to avoid div by zero */
826 if (nralphainrangelow == 0) nralphainrangelow = 1;
827 if (nralphainrangehigh == 0) nralphainrangehigh = 1;
828 alphatest[0] = alphatest[0] + (blockerrlin1 / nralphainrangelow);
829 /* fprintf(stderr, "block err lin low %d, nr %d\n", blockerrlin1, nralphainrangelow);
830 fprintf(stderr, "block err lin high %d, nr %d\n", blockerrlin2, nralphainrangehigh);*/
831 /* again shouldn't really happen often... */
832 if (alphatest[0] < 0) {
833 alphatest[0] = 0;
834 /* fprintf(stderr, "adj alpha base val to 0\n");*/
835 }
836 alphatest[1] = alphatest[1] + (blockerrlin2 / nralphainrangehigh);
837 if (alphatest[1] > 255) {
838 alphatest[1] = 255;
839 /* fprintf(stderr, "adj alpha base val to 255\n");*/
840 }
841
842 alphablockerror3 = 0;
843 for (aindex = 0; aindex < 5; aindex++) {
844 /* don't forget here is always rounded down */
845 acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
846 }
847 for (j = 0; j < numypixels; j++) {
848 for (i = 0; i < numxpixels; i++) {
849 /* maybe it's overkill to have the most complicated calculation just for the error
850 calculation which we only need to figure out if encoding1 or encoding2 is better... */
851 if (srccolors[j][i][3] <= alphatest[0] / 2) {
852 alphaenc3[4*j + i] = 6;
853 alphadist = srccolors[j][i][3];
854 }
855 else if (srccolors[j][i][3] > ((255 + alphatest[1]) / 2)) {
856 alphaenc3[4*j + i] = 7;
857 alphadist = 255 - srccolors[j][i][3];
858 }
859 else if (srccolors[j][i][3] <= acutValues[0]) {
860 alphaenc3[4*j + i] = 0;
861 alphadist = srccolors[j][i][3] - alphatest[0];
862 }
863 else if (srccolors[j][i][3] <= acutValues[1]) {
864 alphaenc3[4*j + i] = 2;
865 alphadist = srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5;
866 }
867 else if (srccolors[j][i][3] <= acutValues[2]) {
868 alphaenc3[4*j + i] = 3;
869 alphadist = srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5;
870 }
871 else if (srccolors[j][i][3] <= acutValues[3]) {
872 alphaenc3[4*j + i] = 4;
873 alphadist = srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5;
874 }
875 else if (srccolors[j][i][3] <= acutValues[4]) {
876 alphaenc3[4*j + i] = 5;
877 alphadist = srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5;
878 }
879 else {
880 alphaenc3[4*j + i] = 1;
881 alphadist = srccolors[j][i][3] - alphatest[1];
882 }
883 alphablockerror3 += alphadist * alphadist;
884 }
885 }
886 }
887 }
888 /* write the alpha values and encoding back. */
889 if ((alphablockerror1 <= alphablockerror2) && (alphablockerror1 <= alphablockerror3)) {
890 /* if (alphablockerror1 > 96) fprintf(stderr, "enc1 used, error %d\n", alphablockerror1);*/
891 writedxt5encodedalphablock( blkaddr, alphause[1], alphause[0], alphaenc1 );
892 }
893 else if (alphablockerror2 <= alphablockerror3) {
894 /* if (alphablockerror2 > 96) fprintf(stderr, "enc2 used, error %d\n", alphablockerror2);*/
895 writedxt5encodedalphablock( blkaddr, alphabase[0], alphabase[1], alphaenc2 );
896 }
897 else {
898 /* fprintf(stderr, "enc3 used, error %d\n", alphablockerror3);*/
899 writedxt5encodedalphablock( blkaddr, (GLubyte)alphatest[0], (GLubyte)alphatest[1], alphaenc3 );
900 }
901 }
902
903 static void extractsrccolors( GLubyte srcpixels[4][4][4], const GLchan *srcaddr,
904 GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps)
905 {
906 GLubyte i, j, c;
907 const GLchan *curaddr;
908 for (j = 0; j < numypixels; j++) {
909 curaddr = srcaddr + j * srcRowStride * comps;
910 for (i = 0; i < numxpixels; i++) {
911 for (c = 0; c < comps; c++) {
912 srcpixels[j][i][c] = *curaddr++ / (CHAN_MAX / 255);
913 }
914 }
915 }
916 }
917
918
919 void tx_compress_dxtn(GLint srccomps, GLint width, GLint height, const GLubyte *srcPixData,
920 GLenum destFormat, GLubyte *dest, GLint dstRowStride)
921 {
922 GLubyte *blkaddr = dest;
923 GLubyte srcpixels[4][4][4];
924 const GLchan *srcaddr = srcPixData;
925 GLint numxpixels, numypixels;
926 GLint i, j;
927 GLint dstRowDiff;
928
929 switch (destFormat) {
930 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
931 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
932 /* hmm we used to get called without dstRowStride... */
933 dstRowDiff = dstRowStride >= (width * 2) ? dstRowStride - (((width + 3) & ~3) * 2) : 0;
934 /* fprintf(stderr, "dxt1 tex width %d tex height %d dstRowStride %d\n",
935 width, height, dstRowStride); */
936 for (j = 0; j < height; j += 4) {
937 if (height > j + 3) numypixels = 4;
938 else numypixels = height - j;
939 srcaddr = srcPixData + j * width * srccomps;
940 for (i = 0; i < width; i += 4) {
941 if (width > i + 3) numxpixels = 4;
942 else numxpixels = width - i;
943 extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps);
944 encodedxtcolorblockfaster(blkaddr, srcpixels, numxpixels, numypixels, destFormat);
945 srcaddr += srccomps * numxpixels;
946 blkaddr += 8;
947 }
948 blkaddr += dstRowDiff;
949 }
950 break;
951 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
952 dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) & ~3) * 4) : 0;
953 /* fprintf(stderr, "dxt3 tex width %d tex height %d dstRowStride %d\n",
954 width, height, dstRowStride); */
955 for (j = 0; j < height; j += 4) {
956 if (height > j + 3) numypixels = 4;
957 else numypixels = height - j;
958 srcaddr = srcPixData + j * width * srccomps;
959 for (i = 0; i < width; i += 4) {
960 if (width > i + 3) numxpixels = 4;
961 else numxpixels = width - i;
962 extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps);
963 *blkaddr++ = (srcpixels[0][0][3] >> 4) | (srcpixels[0][1][3] & 0xf0);
964 *blkaddr++ = (srcpixels[0][2][3] >> 4) | (srcpixels[0][3][3] & 0xf0);
965 *blkaddr++ = (srcpixels[1][0][3] >> 4) | (srcpixels[1][1][3] & 0xf0);
966 *blkaddr++ = (srcpixels[1][2][3] >> 4) | (srcpixels[1][3][3] & 0xf0);
967 *blkaddr++ = (srcpixels[2][0][3] >> 4) | (srcpixels[2][1][3] & 0xf0);
968 *blkaddr++ = (srcpixels[2][2][3] >> 4) | (srcpixels[2][3][3] & 0xf0);
969 *blkaddr++ = (srcpixels[3][0][3] >> 4) | (srcpixels[3][1][3] & 0xf0);
970 *blkaddr++ = (srcpixels[3][2][3] >> 4) | (srcpixels[3][3][3] & 0xf0);
971 encodedxtcolorblockfaster(blkaddr, srcpixels, numxpixels, numypixels, destFormat);
972 srcaddr += srccomps * numxpixels;
973 blkaddr += 8;
974 }
975 blkaddr += dstRowDiff;
976 }
977 break;
978 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
979 dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) & ~3) * 4) : 0;
980 /* fprintf(stderr, "dxt5 tex width %d tex height %d dstRowStride %d\n",
981 width, height, dstRowStride); */
982 for (j = 0; j < height; j += 4) {
983 if (height > j + 3) numypixels = 4;
984 else numypixels = height - j;
985 srcaddr = srcPixData + j * width * srccomps;
986 for (i = 0; i < width; i += 4) {
987 if (width > i + 3) numxpixels = 4;
988 else numxpixels = width - i;
989 extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps);
990 encodedxt5alpha(blkaddr, srcpixels, numxpixels, numypixels);
991 encodedxtcolorblockfaster(blkaddr + 8, srcpixels, numxpixels, numypixels, destFormat);
992 srcaddr += srccomps * numxpixels;
993 blkaddr += 16;
994 }
995 blkaddr += dstRowDiff;
996 }
997 break;
998 default:
999 fprintf(stderr, "libdxtn: Bad dstFormat %d in tx_compress_dxtn\n", destFormat);
1000 return;
1001 }
1002 }