]> git.xonotic.org Git - xonotic/netradiant.git/blob - libs/ddslib/ddslib.c
Wean off #define
[xonotic/netradiant.git] / libs / ddslib / ddslib.c
1 /* -----------------------------------------------------------------------------
2
3    DDS Library
4
5    Based on code from Nvidia's DDS example:
6    http://www.nvidia.com/object/dxtc_decompression_code.html
7
8    Copyright (c) 2003 Randy Reddig
9    All rights reserved.
10
11    Redistribution and use in source and binary forms, with or without modification,
12    are permitted provided that the following conditions are met:
13
14    Redistributions of source code must retain the above copyright notice, this list
15    of conditions and the following disclaimer.
16
17    Redistributions in binary form must reproduce the above copyright notice, this
18    list of conditions and the following disclaimer in the documentation and/or
19    other materials provided with the distribution.
20
21    Neither the names of the copyright holders nor the names of its contributors may
22    be used to endorse or promote products derived from this software without
23    specific prior written permission.
24
25    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
26    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
29    ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
32    ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
36    ----------------------------------------------------------------------------- */
37
38 /* dependencies */
39 #include "ddslib.h"
40
41
42
43 /* endian tomfoolery */
44 typedef union
45 {
46         float f;
47         char c[ 4 ];
48 }
49 floatSwapUnion;
50
51
52 #ifndef __BIG_ENDIAN__
53         #ifdef _SGI_SOURCE
54                 #define __BIG_ENDIAN__
55         #endif
56 #endif
57
58
59 #ifdef __BIG_ENDIAN__
60
61 int   DDSBigLong( int src ) { return src; }
62 short DDSBigShort( short src ) { return src; }
63 float DDSBigFloat( float src ) { return src; }
64
65 int DDSLittleLong( int src ){
66         return ( ( src & 0xFF000000 ) >> 24 ) |
67                    ( ( src & 0x00FF0000 ) >> 8 ) |
68                    ( ( src & 0x0000FF00 ) << 8 ) |
69                    ( ( src & 0x000000FF ) << 24 );
70 }
71
72 short DDSLittleShort( short src ){
73         return ( ( src & 0xFF00 ) >> 8 ) |
74                    ( ( src & 0x00FF ) << 8 );
75 }
76
77 float DDSLittleFloat( float src ){
78         floatSwapUnion in,out;
79         in.f = src;
80         out.c[ 0 ] = in.c[ 3 ];
81         out.c[ 1 ] = in.c[ 2 ];
82         out.c[ 2 ] = in.c[ 1 ];
83         out.c[ 3 ] = in.c[ 0 ];
84         return out.f;
85 }
86
87 #else /*__BIG_ENDIAN__*/
88
89 int   DDSLittleLong( int src ) { return src; }
90 short DDSLittleShort( short src ) { return src; }
91 float DDSLittleFloat( float src ) { return src; }
92
93 int DDSBigLong( int src ){
94         return ( ( src & 0xFF000000 ) >> 24 ) |
95                    ( ( src & 0x00FF0000 ) >> 8 ) |
96                    ( ( src & 0x0000FF00 ) << 8 ) |
97                    ( ( src & 0x000000FF ) << 24 );
98 }
99
100 short DDSBigShort( short src ){
101         return ( ( src & 0xFF00 ) >> 8 ) |
102                    ( ( src & 0x00FF ) << 8 );
103 }
104
105 float DDSBigFloat( float src ){
106         floatSwapUnion in,out;
107         in.f = src;
108         out.c[ 0 ] = in.c[ 3 ];
109         out.c[ 1 ] = in.c[ 2 ];
110         out.c[ 2 ] = in.c[ 1 ];
111         out.c[ 3 ] = in.c[ 0 ];
112         return out.f;
113 }
114
115 #endif /*__BIG_ENDIAN__*/
116
117
118
119 /*
120    DDSDecodePixelFormat()
121    determines which pixel format the dds texture is in
122  */
123
124 static void DDSDecodePixelFormat( ddsBuffer_t *dds, ddsPF_t *pf ){
125         unsigned int fourCC;
126
127
128         /* dummy check */
129         if ( dds == NULL || pf == NULL ) {
130                 return;
131         }
132
133         /* extract fourCC */
134         fourCC = dds->pixelFormat.fourCC;
135
136         /* test it */
137         if ( fourCC == 0 ) {
138                 *pf = DDS_PF_ARGB8888;
139         }
140         else if ( fourCC == *( (unsigned int*) "DXT1" ) ) {
141                 *pf = DDS_PF_DXT1;
142         }
143         else if ( fourCC == *( (unsigned int*) "DXT2" ) ) {
144                 *pf = DDS_PF_DXT2;
145         }
146         else if ( fourCC == *( (unsigned int*) "DXT3" ) ) {
147                 *pf = DDS_PF_DXT3;
148         }
149         else if ( fourCC == *( (unsigned int*) "DXT4" ) ) {
150                 *pf = DDS_PF_DXT4;
151         }
152         else if ( fourCC == *( (unsigned int*) "DXT5" ) ) {
153                 *pf = DDS_PF_DXT5;
154         }
155         else{
156                 *pf = DDS_PF_UNKNOWN;
157         }
158 }
159
160
161
162 /*
163    DDSGetInfo()
164    extracts relevant info from a dds texture, returns 0 on success
165  */
166
167 int DDSGetInfo( ddsBuffer_t *dds, int *width, int *height, ddsPF_t *pf ){
168         /* dummy test */
169         if ( dds == NULL ) {
170                 return -1;
171         }
172
173         /* test dds header */
174         if ( *( (int*) dds->magic ) != *( (int*) "DDS " ) ) {
175                 return -1;
176         }
177         if ( DDSLittleLong( dds->size ) != 124 ) {
178                 return -1;
179         }
180
181         /* extract width and height */
182         if ( width != NULL ) {
183                 *width = DDSLittleLong( dds->width );
184         }
185         if ( height != NULL ) {
186                 *height = DDSLittleLong( dds->height );
187         }
188
189         /* get pixel format */
190         DDSDecodePixelFormat( dds, pf );
191
192         /* return ok */
193         return 0;
194 }
195
196
197
198 /*
199    DDSGetColorBlockColors()
200    extracts colors from a dds color block
201  */
202
203 static void DDSGetColorBlockColors( ddsColorBlock_t *block, ddsColor_t colors[ 4 ] ){
204         unsigned short word;
205
206
207         /* color 0 */
208         word = DDSLittleShort( block->colors[ 0 ] );
209         colors[ 0 ].a = 0xff;
210
211         /* extract rgb bits */
212         colors[ 0 ].b = (unsigned char) word;
213         colors[ 0 ].b <<= 3;
214         colors[ 0 ].b |= ( colors[ 0 ].b >> 5 );
215         word >>= 5;
216         colors[ 0 ].g = (unsigned char) word;
217         colors[ 0 ].g <<= 2;
218         colors[ 0 ].g |= ( colors[ 0 ].g >> 5 );
219         word >>= 6;
220         colors[ 0 ].r = (unsigned char) word;
221         colors[ 0 ].r <<= 3;
222         colors[ 0 ].r |= ( colors[ 0 ].r >> 5 );
223
224         /* same for color 1 */
225         word = DDSLittleShort( block->colors[ 1 ] );
226         colors[ 1 ].a = 0xff;
227
228         /* extract rgb bits */
229         colors[ 1 ].b = (unsigned char) word;
230         colors[ 1 ].b <<= 3;
231         colors[ 1 ].b |= ( colors[ 1 ].b >> 5 );
232         word >>= 5;
233         colors[ 1 ].g = (unsigned char) word;
234         colors[ 1 ].g <<= 2;
235         colors[ 1 ].g |= ( colors[ 1 ].g >> 5 );
236         word >>= 6;
237         colors[ 1 ].r = (unsigned char) word;
238         colors[ 1 ].r <<= 3;
239         colors[ 1 ].r |= ( colors[ 1 ].r >> 5 );
240
241         /* use this for all but the super-freak math method */
242         if ( block->colors[ 0 ] > block->colors[ 1 ] ) {
243                 /* four-color block: derive the other two colors.
244                    00 = color 0, 01 = color 1, 10 = color 2, 11 = color 3
245                    these two bit codes correspond to the 2-bit fields
246                    stored in the 64-bit block. */
247
248                 word = ( (unsigned short) colors[ 0 ].r * 2 + (unsigned short) colors[ 1 ].r ) / 3;
249                 /* no +1 for rounding */
250                 /* as bits have been shifted to 888 */
251                 colors[ 2 ].r = (unsigned char) word;
252                 word = ( (unsigned short) colors[ 0 ].g * 2 + (unsigned short) colors[ 1 ].g ) / 3;
253                 colors[ 2 ].g = (unsigned char) word;
254                 word = ( (unsigned short) colors[ 0 ].b * 2 + (unsigned short) colors[ 1 ].b ) / 3;
255                 colors[ 2 ].b = (unsigned char) word;
256                 colors[ 2 ].a = 0xff;
257
258                 word = ( (unsigned short) colors[ 0 ].r + (unsigned short) colors[ 1 ].r * 2 ) / 3;
259                 colors[ 3 ].r = (unsigned char) word;
260                 word = ( (unsigned short) colors[ 0 ].g + (unsigned short) colors[ 1 ].g * 2 ) / 3;
261                 colors[ 3 ].g = (unsigned char) word;
262                 word = ( (unsigned short) colors[ 0 ].b + (unsigned short) colors[ 1 ].b * 2 ) / 3;
263                 colors[ 3 ].b = (unsigned char) word;
264                 colors[ 3 ].a = 0xff;
265         }
266         else
267         {
268                 /* three-color block: derive the other color.
269                    00 = color 0, 01 = color 1, 10 = color 2,
270                    11 = transparent.
271                    These two bit codes correspond to the 2-bit fields
272                    stored in the 64-bit block */
273
274                 word = ( (unsigned short) colors[ 0 ].r + (unsigned short) colors[ 1 ].r ) / 2;
275                 colors[ 2 ].r = (unsigned char) word;
276                 word = ( (unsigned short) colors[ 0 ].g + (unsigned short) colors[ 1 ].g ) / 2;
277                 colors[ 2 ].g = (unsigned char) word;
278                 word = ( (unsigned short) colors[ 0 ].b + (unsigned short) colors[ 1 ].b ) / 2;
279                 colors[ 2 ].b = (unsigned char) word;
280                 colors[ 2 ].a = 0xff;
281
282                 /* random color to indicate alpha */
283                 colors[ 3 ].r = 0x00;
284                 colors[ 3 ].g = 0xff;
285                 colors[ 3 ].b = 0xff;
286                 colors[ 3 ].a = 0x00;
287         }
288 }
289
290
291
292 /*
293    DDSDecodeColorBlock()
294    decodes a dds color block
295    fixme: make endian-safe
296  */
297
298 static void DDSDecodeColorBlock( unsigned int *pixel, ddsColorBlock_t *block, int width, unsigned int colors[ 4 ] ){
299         int r, n;
300         unsigned int bits;
301         unsigned int masks[] = { 3, 12, 3 << 4, 3 << 6 };       /* bit masks = 00000011, 00001100, 00110000, 11000000 */
302         int shift[] = { 0, 2, 4, 6 };
303
304
305         /* r steps through lines in y */
306         for ( r = 0; r < 4; r++, pixel += ( width - 4 ) )  /* no width * 4 as unsigned int ptr inc will * 4 */
307         {
308                 /* width * 4 bytes per pixel per line, each j dxtc row is 4 lines of pixels */
309
310                 /* n steps through pixels */
311                 for ( n = 0; n < 4; n++ )
312                 {
313                         bits = block->row[ r ] & masks[ n ];
314                         bits >>= shift[ n ];
315
316                         switch ( bits )
317                         {
318                         case 0:
319                                 *pixel = colors[ 0 ];
320                                 pixel++;
321                                 break;
322
323                         case 1:
324                                 *pixel = colors[ 1 ];
325                                 pixel++;
326                                 break;
327
328                         case 2:
329                                 *pixel = colors[ 2 ];
330                                 pixel++;
331                                 break;
332
333                         case 3:
334                                 *pixel = colors[ 3 ];
335                                 pixel++;
336                                 break;
337
338                         default:
339                                 /* invalid */
340                                 pixel++;
341                                 break;
342                         }
343                 }
344         }
345 }
346
347
348
349 /*
350    DDSDecodeAlphaExplicit()
351    decodes a dds explicit alpha block
352  */
353
354 static void DDSDecodeAlphaExplicit( unsigned int *pixel, ddsAlphaBlockExplicit_t *alphaBlock, int width, unsigned int alphaZero ){
355         int row, pix;
356         unsigned short word;
357         ddsColor_t color;
358
359
360         /* clear color */
361         color.r = 0;
362         color.g = 0;
363         color.b = 0;
364
365         /* walk rows */
366         for ( row = 0; row < 4; row++, pixel += ( width - 4 ) )
367         {
368                 word = DDSLittleShort( alphaBlock->row[ row ] );
369
370                 /* walk pixels */
371                 for ( pix = 0; pix < 4; pix++ )
372                 {
373                         /* zero the alpha bits of image pixel */
374                         *pixel &= alphaZero;
375                         color.a = word & 0x000F;
376                         color.a = color.a | ( color.a << 4 );
377                         *pixel |= *( (unsigned int*) &color );
378                         word >>= 4;     /* move next bits to lowest 4 */
379                         pixel++;        /* move to next pixel in the row */
380
381                 }
382         }
383 }
384
385
386
387 /*
388    DDSDecodeAlpha3BitLinear()
389    decodes interpolated alpha block
390  */
391
392 static void DDSDecodeAlpha3BitLinear( unsigned int *pixel, ddsAlphaBlock3BitLinear_t *alphaBlock, int width, unsigned int alphaZero ){
393
394         int row, pix;
395         unsigned int stuff;
396         unsigned char bits[ 4 ][ 4 ];
397         unsigned short alphas[ 8 ];
398         ddsColor_t aColors[ 4 ][ 4 ];
399
400
401         /* get initial alphas */
402         alphas[ 0 ] = alphaBlock->alpha0;
403         alphas[ 1 ] = alphaBlock->alpha1;
404
405         /* 8-alpha block */
406         if ( alphas[ 0 ] > alphas[ 1 ] ) {
407                 /* 000 = alpha_0, 001 = alpha_1, others are interpolated */
408                 alphas[ 2 ] = ( 6 * alphas[ 0 ] +     alphas[ 1 ] ) / 7; /* bit code 010 */
409                 alphas[ 3 ] = ( 5 * alphas[ 0 ] + 2 * alphas[ 1 ] ) / 7; /* bit code 011 */
410                 alphas[ 4 ] = ( 4 * alphas[ 0 ] + 3 * alphas[ 1 ] ) / 7; /* bit code 100 */
411                 alphas[ 5 ] = ( 3 * alphas[ 0 ] + 4 * alphas[ 1 ] ) / 7; /* bit code 101 */
412                 alphas[ 6 ] = ( 2 * alphas[ 0 ] + 5 * alphas[ 1 ] ) / 7; /* bit code 110 */
413                 alphas[ 7 ] = (     alphas[ 0 ] + 6 * alphas[ 1 ] ) / 7; /* bit code 111 */
414         }
415
416         /* 6-alpha block */
417         else
418         {
419                 /* 000 = alpha_0, 001 = alpha_1, others are interpolated */
420                 alphas[ 2 ] = ( 4 * alphas[ 0 ] +     alphas[ 1 ] ) / 5;  /* bit code 010 */
421                 alphas[ 3 ] = ( 3 * alphas[ 0 ] + 2 * alphas[ 1 ] ) / 5;  /* bit code 011 */
422                 alphas[ 4 ] = ( 2 * alphas[ 0 ] + 3 * alphas[ 1 ] ) / 5;  /* bit code 100 */
423                 alphas[ 5 ] = (    alphas[ 0 ] + 4 * alphas[ 1 ] ) / 5;  /* bit code 101 */
424                 alphas[ 6 ] = 0;                                        /* bit code 110 */
425                 alphas[ 7 ] = 255;                                      /* bit code 111 */
426         }
427
428         /* decode 3-bit fields into array of 16 bytes with same value */
429
430         /* first two rows of 4 pixels each */
431         stuff = *( (unsigned int*) &( alphaBlock->stuff[ 0 ] ) );
432
433         bits[ 0 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
434         stuff >>= 3;
435         bits[ 0 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
436         stuff >>= 3;
437         bits[ 0 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
438         stuff >>= 3;
439         bits[ 0 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
440         stuff >>= 3;
441         bits[ 1 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
442         stuff >>= 3;
443         bits[ 1 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
444         stuff >>= 3;
445         bits[ 1 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
446         stuff >>= 3;
447         bits[ 1 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
448
449         /* last two rows */
450         stuff = *( (unsigned int*) &( alphaBlock->stuff[ 3 ] ) ); /* last 3 bytes */
451
452         bits[ 2 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
453         stuff >>= 3;
454         bits[ 2 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
455         stuff >>= 3;
456         bits[ 2 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
457         stuff >>= 3;
458         bits[ 2 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
459         stuff >>= 3;
460         bits[ 3 ][ 0 ] = (unsigned char) ( stuff & 0x00000007 );
461         stuff >>= 3;
462         bits[ 3 ][ 1 ] = (unsigned char) ( stuff & 0x00000007 );
463         stuff >>= 3;
464         bits[ 3 ][ 2 ] = (unsigned char) ( stuff & 0x00000007 );
465         stuff >>= 3;
466         bits[ 3 ][ 3 ] = (unsigned char) ( stuff & 0x00000007 );
467
468         /* decode the codes into alpha values */
469         for ( row = 0; row < 4; row++ )
470         {
471                 for ( pix = 0; pix < 4; pix++ )
472                 {
473                         aColors[ row ][ pix ].r = 0;
474                         aColors[ row ][ pix ].g = 0;
475                         aColors[ row ][ pix ].b = 0;
476                         aColors[ row ][ pix ].a = (unsigned char) alphas[ bits[ row ][ pix ] ];
477                 }
478         }
479
480         /* write out alpha values to the image bits */
481         for ( row = 0; row < 4; row++, pixel += width - 4 )
482         {
483                 for ( pix = 0; pix < 4; pix++ )
484                 {
485                         /* zero the alpha bits of image pixel */
486                         *pixel &= alphaZero;
487
488                         /* or the bits into the prev. nulled alpha */
489                         *pixel |= *( (unsigned int*) &( aColors[ row ][ pix ] ) );
490                         pixel++;
491                 }
492         }
493 }
494
495
496
497 /*
498    DDSDecompressDXT1()
499    decompresses a dxt1 format texture
500  */
501
502 static int DDSDecompressDXT1( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
503         int x, y, xBlocks, yBlocks;
504         unsigned int    *pixel;
505         ddsColorBlock_t *block;
506         ddsColor_t colors[ 4 ];
507
508
509         /* setup */
510         xBlocks = width / 4;
511         yBlocks = height / 4;
512
513         /* walk y */
514         for ( y = 0; y < yBlocks; y++ )
515         {
516                 /* 8 bytes per block */
517                 block = (ddsColorBlock_t*) ( (char *) dds->data + y * xBlocks * 8 );
518
519                 /* walk x */
520                 for ( x = 0; x < xBlocks; x++, block++ )
521                 {
522                         DDSGetColorBlockColors( block, colors );
523                         pixel = (unsigned int*) ( pixels + x * 16 + ( y * 4 ) * width * 4 );
524                         DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
525                 }
526         }
527
528         /* return ok */
529         return 0;
530 }
531
532
533
534 /*
535    DDSDecompressDXT3()
536    decompresses a dxt3 format texture
537  */
538
539 static int DDSDecompressDXT3( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
540         int x, y, xBlocks, yBlocks;
541         unsigned int            *pixel, alphaZero;
542         ddsColorBlock_t         *block;
543         ddsAlphaBlockExplicit_t *alphaBlock;
544         ddsColor_t colors[ 4 ];
545
546
547         /* setup */
548         xBlocks = width / 4;
549         yBlocks = height / 4;
550
551         /* create zero alpha */
552         colors[ 0 ].a = 0;
553         colors[ 0 ].r = 0xFF;
554         colors[ 0 ].g = 0xFF;
555         colors[ 0 ].b = 0xFF;
556         alphaZero = *( (unsigned int*) &colors[ 0 ] );
557
558         /* walk y */
559         for ( y = 0; y < yBlocks; y++ )
560         {
561                 /* 8 bytes per block, 1 block for alpha, 1 block for color */
562                 block = (ddsColorBlock_t*) ( (char *) dds->data + y * xBlocks * 16 );
563
564                 /* walk x */
565                 for ( x = 0; x < xBlocks; x++, block++ )
566                 {
567                         /* get alpha block */
568                         alphaBlock = (ddsAlphaBlockExplicit_t*) block;
569
570                         /* get color block */
571                         block++;
572                         DDSGetColorBlockColors( block, colors );
573
574                         /* decode color block */
575                         pixel = (unsigned int*) ( pixels + x * 16 + ( y * 4 ) * width * 4 );
576                         DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
577
578                         /* overwrite alpha bits with alpha block */
579                         DDSDecodeAlphaExplicit( pixel, alphaBlock, width, alphaZero );
580                 }
581         }
582
583         /* return ok */
584         return 0;
585 }
586
587
588
589 /*
590    DDSDecompressDXT5()
591    decompresses a dxt5 format texture
592  */
593
594 static int DDSDecompressDXT5( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
595         int x, y, xBlocks, yBlocks;
596         unsigned int                *pixel, alphaZero;
597         ddsColorBlock_t             *block;
598         ddsAlphaBlock3BitLinear_t   *alphaBlock;
599         ddsColor_t colors[ 4 ];
600
601
602         /* setup */
603         xBlocks = width / 4;
604         yBlocks = height / 4;
605
606         /* create zero alpha */
607         colors[ 0 ].a = 0;
608         colors[ 0 ].r = 0xFF;
609         colors[ 0 ].g = 0xFF;
610         colors[ 0 ].b = 0xFF;
611         alphaZero = *( (unsigned int*) &colors[ 0 ] );
612
613         /* walk y */
614         for ( y = 0; y < yBlocks; y++ )
615         {
616                 /* 8 bytes per block, 1 block for alpha, 1 block for color */
617                 block = (ddsColorBlock_t*) ( (char *) dds->data + y * xBlocks * 16 );
618
619                 /* walk x */
620                 for ( x = 0; x < xBlocks; x++, block++ )
621                 {
622                         /* get alpha block */
623                         alphaBlock = (ddsAlphaBlock3BitLinear_t*) block;
624
625                         /* get color block */
626                         block++;
627                         DDSGetColorBlockColors( block, colors );
628
629                         /* decode color block */
630                         pixel = (unsigned int*) ( pixels + x * 16 + ( y * 4 ) * width * 4 );
631                         DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
632
633                         /* overwrite alpha bits with alpha block */
634                         DDSDecodeAlpha3BitLinear( pixel, alphaBlock, width, alphaZero );
635                 }
636         }
637
638         /* return ok */
639         return 0;
640 }
641
642
643
644 /*
645    DDSDecompressDXT2()
646    decompresses a dxt2 format texture (fixme: un-premultiply alpha)
647  */
648
649 static int DDSDecompressDXT2( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
650         int r;
651
652
653         /* decompress dxt3 first */
654         r = DDSDecompressDXT3( dds, width, height, pixels );
655
656         /* return to sender */
657         return r;
658 }
659
660
661
662 /*
663    DDSDecompressDXT4()
664    decompresses a dxt4 format texture (fixme: un-premultiply alpha)
665  */
666
667 static int DDSDecompressDXT4( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
668         int r;
669
670
671         /* decompress dxt5 first */
672         r = DDSDecompressDXT5( dds, width, height, pixels );
673
674         /* return to sender */
675         return r;
676 }
677
678
679
680 /*
681    DDSDecompressARGB8888()
682    decompresses an argb 8888 format texture
683  */
684
685 static int DDSDecompressARGB8888( ddsBuffer_t *dds, int width, int height, unsigned char *pixels ){
686         int x, y;
687         unsigned char               *in, *out;
688
689
690         /* setup */
691         in = dds->data;
692         out = pixels;
693
694         /* walk y */
695         for ( y = 0; y < height; y++ )
696         {
697                 /* walk x */
698                 for ( x = 0; x < width; x++ )
699                 {
700                         *out++ = *in++;
701                         *out++ = *in++;
702                         *out++ = *in++;
703                         *out++ = *in++;
704                 }
705         }
706
707         /* return ok */
708         return 0;
709 }
710
711
712
713 /*
714    DDSDecompress()
715    decompresses a dds texture into an rgba image buffer, returns 0 on success
716  */
717
718 int DDSDecompress( ddsBuffer_t *dds, unsigned char *pixels ){
719         int width, height, r;
720         ddsPF_t pf;
721
722
723         /* get dds info */
724         r = DDSGetInfo( dds, &width, &height, &pf );
725         if ( r ) {
726                 return r;
727         }
728
729         /* decompress */
730         switch ( pf )
731         {
732         case DDS_PF_ARGB8888:
733                 /* fixme: support other [a]rgb formats */
734                 r = DDSDecompressARGB8888( dds, width, height, pixels );
735                 break;
736
737         case DDS_PF_DXT1:
738                 r = DDSDecompressDXT1( dds, width, height, pixels );
739                 break;
740
741         case DDS_PF_DXT2:
742                 r = DDSDecompressDXT2( dds, width, height, pixels );
743                 break;
744
745         case DDS_PF_DXT3:
746                 r = DDSDecompressDXT3( dds, width, height, pixels );
747                 break;
748
749         case DDS_PF_DXT4:
750                 r = DDSDecompressDXT4( dds, width, height, pixels );
751                 break;
752
753         case DDS_PF_DXT5:
754                 r = DDSDecompressDXT5( dds, width, height, pixels );
755                 break;
756
757         default:
758         case DDS_PF_UNKNOWN:
759                 memset( pixels, 0xFF, width * height * 4 );
760                 r = -1;
761                 break;
762         }
763
764         /* return to sender */
765         return r;
766 }