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