5 * Copyright (C) 2004 Roland Scheidegger All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
26 #include <OpenGL/gl.h>
31 typedef GLubyte GLchan
;
32 #define UBYTE_TO_CHAN(b) (b)
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
);
48 void tx_compress_dxtn(GLint srccomps
, GLint width
, GLint height
,
49 const GLubyte
*srcPixData
, GLenum destformat
,
50 GLubyte
*dest
, GLint dstRowStride
);
52 #define EXP5TO8R(packedcol) \
53 ((((packedcol) >> 8) & 0xf8) | (((packedcol) >> 13) & 0x7))
55 #define EXP6TO8G(packedcol) \
56 ((((packedcol) >> 3) & 0xfc) | (((packedcol) >> 9) & 0x3))
58 #define EXP5TO8B(packedcol) \
59 ((((packedcol) << 3) & 0xf8) | (((packedcol) >> 2) & 0x7))
61 #define EXP4TO8(col) \
62 ((col) | ((col) << 4))
64 /* inefficient. To be efficient, it would be necessary to decode 16 pixels at once */
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);
77 rgba
[ACOMP
] = CHAN_MAX
;
80 rgba
[RCOMP
] = UBYTE_TO_CHAN( EXP5TO8R(color0
) );
81 rgba
[GCOMP
] = UBYTE_TO_CHAN( EXP6TO8G(color0
) );
82 rgba
[BCOMP
] = UBYTE_TO_CHAN( EXP5TO8B(color0
) );
85 rgba
[RCOMP
] = UBYTE_TO_CHAN( EXP5TO8R(color1
) );
86 rgba
[GCOMP
] = UBYTE_TO_CHAN( EXP6TO8G(color1
) );
87 rgba
[BCOMP
] = UBYTE_TO_CHAN( EXP5TO8B(color1
) );
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) );
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) );
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) );
111 if (dxt_type
== 1) rgba
[ACOMP
] = UBYTE_TO_CHAN(0);
115 /* CANNOT happen (I hope) */
121 void fetch_2d_texel_rgb_dxt1(GLint srcRowStride
, const GLubyte
*pixdata
,
122 GLint i
, GLint j
, GLvoid
*texel
)
124 /* Extract the (i,j) pixel from pixdata and return it
125 * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP].
128 const GLubyte
*blksrc
= (pixdata
+ ((srcRowStride
+ 3) / 4 * (j
/ 4) + (i
/ 4)) * 8);
129 dxt135_decode_imageblock(blksrc
, (i
&3), (j
&3), 0, texel
);
133 void fetch_2d_texel_rgba_dxt1(GLint srcRowStride
, const GLubyte
*pixdata
,
134 GLint i
, GLint j
, GLvoid
*texel
)
136 /* Extract the (i,j) pixel from pixdata and return it
137 * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP].
140 const GLubyte
*blksrc
= (pixdata
+ ((srcRowStride
+ 3) / 4 * (j
/ 4) + (i
/ 4)) * 8);
141 dxt135_decode_imageblock(blksrc
, (i
&3), (j
&3), 1, texel
);
144 void fetch_2d_texel_rgba_dxt3(GLint srcRowStride
, const GLubyte
*pixdata
,
145 GLint i
, GLint j
, GLvoid
*texel
) {
147 /* Extract the (i,j) pixel from pixdata and return it
148 * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP].
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
)) );
158 void fetch_2d_texel_rgba_dxt5(GLint srcRowStride
, const GLubyte
*pixdata
,
159 GLint i
, GLint j
, GLvoid
*texel
) {
161 /* Extract the (i,j) pixel from pixdata and return it
162 * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP].
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
);
176 rgba
[ACOMP
] = UBYTE_TO_CHAN( alpha0
);
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) );
182 rgba
[ACOMP
] = UBYTE_TO_CHAN( ((alpha0
* (6 - code
) + (alpha1
* (code
- 1))) / 5) );
186 rgba
[ACOMP
] = CHAN_MAX
;
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 */
193 #define GREENWEIGHT 16
198 static void fancybasecolorsearch( GLubyte
*blkaddr
, GLubyte srccolors
[4][4][4], GLubyte
*bestcolor
[2],
199 GLint numxpixels
, GLint numypixels
, GLint type
, GLboolean haveAlpha
)
201 /* use same luminance-weighted distance metric to determine encoding as for finding the base colors */
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];
210 GLint pixerrorcolorbest
[3];
213 GLubyte testcolor
[2][3];
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];
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];
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;
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;
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
) {
267 pixerrorbest
= pixerror
;
268 pixerrorcolorbest
[0] = pixerrorred
;
269 pixerrorcolorbest
[1] = pixerrorgreen
;
270 pixerrorcolorbest
[2] = pixerrorblue
;
274 for (z
= 0; z
< 3; z
++) {
275 blockerrlin
[0][z
] += 3 * pixerrorcolorbest
[z
];
280 for (z
= 0; z
< 3; z
++) {
281 blockerrlin
[0][z
] += 2 * pixerrorcolorbest
[z
];
284 for (z
= 0; z
< 3; z
++) {
285 blockerrlin
[1][z
] += 1 * pixerrorcolorbest
[z
];
290 for (z
= 0; z
< 3; z
++) {
291 blockerrlin
[0][z
] += 1 * pixerrorcolorbest
[z
];
294 for (z
= 0; z
< 3; z
++) {
295 blockerrlin
[1][z
] += 2 * pixerrorcolorbest
[z
];
300 for (z
= 0; z
< 3; z
++) {
301 blockerrlin
[1][z
] += 3 * pixerrorcolorbest
[z
];
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
];
314 else if (newvalue
>= 255)
315 testcolor
[j
][i
] = 255;
316 else testcolor
[j
][i
] = newvalue
;
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
;
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;
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]) {
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;
353 if ((testcolor
[ind0
][0] + factor
* coldiffred
) <= 255)
354 testcolor
[ind0
][0] += factor
* coldiffred
;
355 else testcolor
[ind0
][0] = 255;
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;
363 if ((testcolor
[ind0
][2] + factor
* coldiffblue
) <= 255)
364 testcolor
[ind0
][2] += factor
* coldiffblue
;
365 else testcolor
[ind0
][2] = 255;
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
];
378 for (i
= 0; i
< 3; i
++) {
379 bestcolor
[0][i
] = testcolor
[1][i
];
380 bestcolor
[1][i
] = testcolor
[0][i
];
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]);*/
390 static void storedxtencodedblock( GLubyte
*blkaddr
, GLubyte srccolors
[4][4][4], GLubyte
*bestcolor
[2],
391 GLint numxpixels
, GLint numypixels
, GLuint type
, GLboolean haveAlpha
)
393 /* use same luminance-weighted distance metric to determine encoding as for finding the base colors */
396 GLuint testerror
, testerror2
, pixerror
, pixerrorbest
;
398 GLushort color0
, color1
, tempcolor
;
399 GLuint bits
= 0, bits2
= 0;
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;
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
;
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;
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
;
442 testerror
+= pixerrorbest
;
443 bits
|= enc
<< (2 * (j
* 4 + i
));
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 */
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
)) {
463 pixerrorbest
= 0; /* don't calculate error */
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;
482 testerror2
+= pixerrorbest
;
483 bits2
|= enc
<< (2 * (j
* 4 + i
));
487 testerror2
= 0xffffffff;
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;
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;
513 static void encodedxtcolorblockfaster( GLubyte
*blkaddr
, GLubyte srccolors
[4][4][4],
514 GLint numxpixels
, GLint numypixels
, GLuint type
)
516 /* simplistic approach. We need two base colors, simply use the "highest" and the "lowest" color
517 present in the picture as base colors */
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 */
524 GLubyte
*bestcolor
[2];
525 GLubyte basecolors
[2][3];
527 GLuint lowcv
, highcv
, testcv
;
528 GLboolean haveAlpha
= GL_FALSE
;
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
) {
543 bestcolor
[1] = srccolors
[j
][i
];
545 else if (testcv
< lowcv
) {
547 bestcolor
[0] = srccolors
[j
][i
];
550 else haveAlpha
= GL_TRUE
;
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
];
559 bestcolor
[0] = basecolors
[0];
560 bestcolor
[1] = basecolors
[1];
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
);
568 static void writedxt5encodedalphablock( GLubyte
*blkaddr
, GLubyte alphabase1
, GLubyte alphabase2
,
569 GLubyte alphaenc
[16])
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);
581 static void encodedxt5alpha(GLubyte
*blkaddr
, GLubyte srccolors
[4][4][4],
582 GLint numxpixels
, GLint numypixels
)
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
;
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
;
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];
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 */
616 *blkaddr
++ = srccolors
[0][0][3];
624 /* fprintf(stderr, "enc0 used\n");*/
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;
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];
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;
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;
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;
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;
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;
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;
676 alphaenc1
[4*j
+ i
] = 1;
677 alphadist
= srccolors
[j
][i
][3] - alphause
[0];
679 alphablockerror1
+= alphadist
* alphadist
;
682 /* for (i = 0; i < 16; i++) {
683 fprintf(stderr, "%d ", alphaenc1[i]);
685 fprintf(stderr, "cutVals ");
686 for (i = 0; i < 8; i++) {
687 fprintf(stderr, "%d ", acutValues[i]);
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]);
695 fprintf(stderr, "\n");
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) {
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;
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;
716 else if (srccolors
[j
][i
][3] == 255) {
717 alphaenc2
[4*j
+ i
] = 7;
720 else if (srccolors
[j
][i
][3] <= acutValues
[0]) {
721 alphaenc2
[4*j
+ i
] = 0;
722 alphadist
= srccolors
[j
][i
][3] - alphabase
[0];
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;
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;
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;
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;
741 alphaenc2
[4*j
+ i
] = 1;
742 alphadist
= srccolors
[j
][i
][3] - alphabase
[1];
744 alphablockerror2
+= alphadist
* alphadist
;
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;
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];
767 /* shouldn't happen too often, don't really care about those degenerated cases */
768 if (alphatest
[1] <= alphatest
[0]) {
771 /* fprintf(stderr, "only 1 or 0 colors for encoding!\n");*/
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;
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
785 for (j
= 0; j
< numypixels
; j
++) {
786 for (i
= 0; i
< numxpixels
; i
++) {
787 if (srccolors
[j
][i
][3] <= alphatest
[0] / 2) {
789 else if (srccolors
[j
][i
][3] > ((255 + alphatest
[1]) / 2)) {
791 else if (srccolors
[j
][i
][3] <= acutValues
[0]) {
792 blockerrlin1
+= (srccolors
[j
][i
][3] - alphatest
[0]);
793 nralphainrangelow
+= 1;
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;
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;
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;
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;
820 blockerrlin2
+= (srccolors
[j
][i
][3] - alphatest
[1]);
821 nralphainrangehigh
+= 1;
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) {
834 /* fprintf(stderr, "adj alpha base val to 0\n");*/
836 alphatest
[1] = alphatest
[1] + (blockerrlin2
/ nralphainrangehigh
);
837 if (alphatest
[1] > 255) {
839 /* fprintf(stderr, "adj alpha base val to 255\n");*/
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;
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];
855 else if (srccolors
[j
][i
][3] > ((255 + alphatest
[1]) / 2)) {
856 alphaenc3
[4*j
+ i
] = 7;
857 alphadist
= 255 - srccolors
[j
][i
][3];
859 else if (srccolors
[j
][i
][3] <= acutValues
[0]) {
860 alphaenc3
[4*j
+ i
] = 0;
861 alphadist
= srccolors
[j
][i
][3] - alphatest
[0];
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;
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;
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;
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;
880 alphaenc3
[4*j
+ i
] = 1;
881 alphadist
= srccolors
[j
][i
][3] - alphatest
[1];
883 alphablockerror3
+= alphadist
* alphadist
;
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
);
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
);
898 /* fprintf(stderr, "enc3 used, error %d\n", alphablockerror3);*/
899 writedxt5encodedalphablock( blkaddr
, (GLubyte
)alphatest
[0], (GLubyte
)alphatest
[1], alphaenc3
);
903 static void extractsrccolors( GLubyte srcpixels
[4][4][4], const GLchan
*srcaddr
,
904 GLint srcRowStride
, GLint numxpixels
, GLint numypixels
, GLint comps
)
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);
919 void tx_compress_dxtn(GLint srccomps
, GLint width
, GLint height
, const GLubyte
*srcPixData
,
920 GLenum destFormat
, GLubyte
*dest
, GLint dstRowStride
)
922 GLubyte
*blkaddr
= dest
;
923 GLubyte srcpixels
[4][4][4];
924 const GLchan
*srcaddr
= srcPixData
;
925 GLint numxpixels
, numypixels
;
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
;
948 blkaddr
+= dstRowDiff
;
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
;
975 blkaddr
+= dstRowDiff
;
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
;
995 blkaddr
+= dstRowDiff
;
999 fprintf(stderr
, "libdxtn: Bad dstFormat %d in tx_compress_dxtn\n", destFormat
);