b179432da4a9e9cfbe6fcd18276db683bbc87c3d
[blender-staging.git] / source / blender / imbuf / intern / dds / DirectDrawSurface.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * Contributors: Amorilia (amorilia@users.sourceforge.net)
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file blender/imbuf/intern/dds/DirectDrawSurface.cpp
26  *  \ingroup imbdds
27  */
28
29
30 /*
31  * This file is based on a similar file from the NVIDIA texture tools
32  * (http://nvidia-texture-tools.googlecode.com/)
33  *
34  * Original license from NVIDIA follows.
35  */
36
37 // Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
38 // 
39 // Permission is hereby granted, free of charge, to any person
40 // obtaining a copy of this software and associated documentation
41 // files (the "Software"), to deal in the Software without
42 // restriction, including without limitation the rights to use,
43 // copy, modify, merge, publish, distribute, sublicense, and/or sell
44 // copies of the Software, and to permit persons to whom the
45 // Software is furnished to do so, subject to the following
46 // conditions:
47 // 
48 // The above copyright notice and this permission notice shall be
49 // included in all copies or substantial portions of the Software.
50 // 
51 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
52 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
53 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
54 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
55 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
56 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
57 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
58 // OTHER DEALINGS IN THE SOFTWARE.
59
60 #include <DirectDrawSurface.h>
61 #include <BlockDXT.h>
62 #include <PixelFormat.h>
63
64 #include <stdio.h> // printf
65 #include <math.h>  // sqrt
66 #include <sys/types.h>
67
68 /*** declarations ***/
69
70 #if !defined(MAKEFOURCC)
71 #       define MAKEFOURCC(ch0, ch1, ch2, ch3) \
72                 ((uint)((unsigned char)(ch0)) | \
73                 ((uint)((unsigned char)(ch1)) << 8) | \
74                 ((uint)((unsigned char)(ch2)) << 16) | \
75                 ((uint)((unsigned char)(ch3)) << 24 ))
76 #endif
77
78 static const uint FOURCC_DDS = MAKEFOURCC('D', 'D', 'S', ' ');
79 static const uint FOURCC_DXT1 = MAKEFOURCC('D', 'X', 'T', '1');
80 static const uint FOURCC_DXT2 = MAKEFOURCC('D', 'X', 'T', '2');
81 static const uint FOURCC_DXT3 = MAKEFOURCC('D', 'X', 'T', '3');
82 static const uint FOURCC_DXT4 = MAKEFOURCC('D', 'X', 'T', '4');
83 static const uint FOURCC_DXT5 = MAKEFOURCC('D', 'X', 'T', '5');
84 static const uint FOURCC_RXGB = MAKEFOURCC('R', 'X', 'G', 'B');
85 static const uint FOURCC_ATI1 = MAKEFOURCC('A', 'T', 'I', '1');
86 static const uint FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2');
87
88 static const uint FOURCC_A2XY = MAKEFOURCC('A', '2', 'X', 'Y');
89         
90 static const uint FOURCC_DX10 = MAKEFOURCC('D', 'X', '1', '0');
91
92 // 32 bit RGB formats.
93 static const uint D3DFMT_R8G8B8 = 20;
94 static const uint D3DFMT_A8R8G8B8 = 21;
95 static const uint D3DFMT_X8R8G8B8 = 22;
96 static const uint D3DFMT_R5G6B5 = 23;
97 static const uint D3DFMT_X1R5G5B5 = 24;
98 static const uint D3DFMT_A1R5G5B5 = 25;
99 static const uint D3DFMT_A4R4G4B4 = 26;
100 static const uint D3DFMT_R3G3B2 = 27;
101 static const uint D3DFMT_A8 = 28;
102 static const uint D3DFMT_A8R3G3B2 = 29;
103 static const uint D3DFMT_X4R4G4B4 = 30;
104 static const uint D3DFMT_A2B10G10R10 = 31;
105 static const uint D3DFMT_A8B8G8R8 = 32;
106 static const uint D3DFMT_X8B8G8R8 = 33;
107 static const uint D3DFMT_G16R16 = 34;
108 static const uint D3DFMT_A2R10G10B10 = 35;
109
110 static const uint D3DFMT_A16B16G16R16 = 36;
111
112 // Palette formats.
113 static const uint D3DFMT_A8P8 = 40;
114 static const uint D3DFMT_P8 = 41;
115         
116 // Luminance formats.
117 static const uint D3DFMT_L8 = 50;
118 static const uint D3DFMT_A8L8 = 51;
119 static const uint D3DFMT_A4L4 = 52;
120 static const uint D3DFMT_L16 = 81;
121
122 // Floating point formats
123 static const uint D3DFMT_R16F = 111;
124 static const uint D3DFMT_G16R16F = 112;
125 static const uint D3DFMT_A16B16G16R16F = 113;
126 static const uint D3DFMT_R32F = 114;
127 static const uint D3DFMT_G32R32F = 115;
128 static const uint D3DFMT_A32B32G32R32F = 116;
129         
130 static const uint DDSD_CAPS = 0x00000001U;
131 static const uint DDSD_PIXELFORMAT = 0x00001000U;
132 static const uint DDSD_WIDTH = 0x00000004U;
133 static const uint DDSD_HEIGHT = 0x00000002U;
134 static const uint DDSD_PITCH = 0x00000008U;
135 static const uint DDSD_MIPMAPCOUNT = 0x00020000U;
136 static const uint DDSD_LINEARSIZE = 0x00080000U;
137 static const uint DDSD_DEPTH = 0x00800000U;
138         
139 static const uint DDSCAPS_COMPLEX = 0x00000008U;
140 static const uint DDSCAPS_TEXTURE = 0x00001000U;
141 static const uint DDSCAPS_MIPMAP = 0x00400000U;
142 static const uint DDSCAPS2_VOLUME = 0x00200000U;
143 static const uint DDSCAPS2_CUBEMAP = 0x00000200U;
144
145 static const uint DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400U;
146 static const uint DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800U;
147 static const uint DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000U;
148 static const uint DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000U;
149 static const uint DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000U;
150 static const uint DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000U;
151 static const uint DDSCAPS2_CUBEMAP_ALL_FACES = 0x0000FC00U;
152
153 static const uint DDPF_ALPHAPIXELS = 0x00000001U;
154 static const uint DDPF_ALPHA = 0x00000002U;
155 static const uint DDPF_FOURCC = 0x00000004U;
156 static const uint DDPF_RGB = 0x00000040U;
157 static const uint DDPF_PALETTEINDEXED1 = 0x00000800U;
158 static const uint DDPF_PALETTEINDEXED2 = 0x00001000U;
159 static const uint DDPF_PALETTEINDEXED4 = 0x00000008U;
160 static const uint DDPF_PALETTEINDEXED8 = 0x00000020U;
161 static const uint DDPF_LUMINANCE = 0x00020000U;
162 static const uint DDPF_ALPHAPREMULT = 0x00008000U;
163 static const uint DDPF_NORMAL = 0x80000000U;    // @@ Custom nv flag.
164
165         // DX10 formats.
166         enum DXGI_FORMAT
167         {
168                 DXGI_FORMAT_UNKNOWN = 0,
169                 
170                 DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
171                 DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
172                 DXGI_FORMAT_R32G32B32A32_UINT = 3,
173                 DXGI_FORMAT_R32G32B32A32_SINT = 4,
174                 
175                 DXGI_FORMAT_R32G32B32_TYPELESS = 5,
176                 DXGI_FORMAT_R32G32B32_FLOAT = 6,
177                 DXGI_FORMAT_R32G32B32_UINT = 7,
178                 DXGI_FORMAT_R32G32B32_SINT = 8,
179                 
180                 DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
181                 DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
182                 DXGI_FORMAT_R16G16B16A16_UNORM = 11,
183                 DXGI_FORMAT_R16G16B16A16_UINT = 12,
184                 DXGI_FORMAT_R16G16B16A16_SNORM = 13,
185                 DXGI_FORMAT_R16G16B16A16_SINT = 14,
186                 
187                 DXGI_FORMAT_R32G32_TYPELESS = 15,
188                 DXGI_FORMAT_R32G32_FLOAT = 16,
189                 DXGI_FORMAT_R32G32_UINT = 17,
190                 DXGI_FORMAT_R32G32_SINT = 18,
191                 
192                 DXGI_FORMAT_R32G8X24_TYPELESS = 19,
193                 DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
194                 DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
195                 DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
196                 
197                 DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
198                 DXGI_FORMAT_R10G10B10A2_UNORM = 24,
199                 DXGI_FORMAT_R10G10B10A2_UINT = 25,
200                 
201                 DXGI_FORMAT_R11G11B10_FLOAT = 26,
202                 
203                 DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
204                 DXGI_FORMAT_R8G8B8A8_UNORM = 28,
205                 DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
206                 DXGI_FORMAT_R8G8B8A8_UINT = 30,
207                 DXGI_FORMAT_R8G8B8A8_SNORM = 31,
208                 DXGI_FORMAT_R8G8B8A8_SINT = 32,
209                 
210                 DXGI_FORMAT_R16G16_TYPELESS = 33,
211                 DXGI_FORMAT_R16G16_FLOAT = 34,
212                 DXGI_FORMAT_R16G16_UNORM = 35,
213                 DXGI_FORMAT_R16G16_UINT = 36,
214                 DXGI_FORMAT_R16G16_SNORM = 37,
215                 DXGI_FORMAT_R16G16_SINT = 38,
216                 
217                 DXGI_FORMAT_R32_TYPELESS = 39,
218                 DXGI_FORMAT_D32_FLOAT = 40,
219                 DXGI_FORMAT_R32_FLOAT = 41,
220                 DXGI_FORMAT_R32_UINT = 42,
221                 DXGI_FORMAT_R32_SINT = 43,
222                 
223                 DXGI_FORMAT_R24G8_TYPELESS = 44,
224                 DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
225                 DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
226                 DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
227                 
228                 DXGI_FORMAT_R8G8_TYPELESS = 48,
229                 DXGI_FORMAT_R8G8_UNORM = 49,
230                 DXGI_FORMAT_R8G8_UINT = 50,
231                 DXGI_FORMAT_R8G8_SNORM = 51,
232                 DXGI_FORMAT_R8G8_SINT = 52,
233                 
234                 DXGI_FORMAT_R16_TYPELESS = 53,
235                 DXGI_FORMAT_R16_FLOAT = 54,
236                 DXGI_FORMAT_D16_UNORM = 55,
237                 DXGI_FORMAT_R16_UNORM = 56,
238                 DXGI_FORMAT_R16_UINT = 57,
239                 DXGI_FORMAT_R16_SNORM = 58,
240                 DXGI_FORMAT_R16_SINT = 59,
241                 
242                 DXGI_FORMAT_R8_TYPELESS = 60,
243                 DXGI_FORMAT_R8_UNORM = 61,
244                 DXGI_FORMAT_R8_UINT = 62,
245                 DXGI_FORMAT_R8_SNORM = 63,
246                 DXGI_FORMAT_R8_SINT = 64,
247                 DXGI_FORMAT_A8_UNORM = 65,
248                 
249                 DXGI_FORMAT_R1_UNORM = 66,
250                 
251                 DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
252                 
253                 DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
254                 DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
255                 
256                 DXGI_FORMAT_BC1_TYPELESS = 70,
257                 DXGI_FORMAT_BC1_UNORM = 71,
258                 DXGI_FORMAT_BC1_UNORM_SRGB = 72,
259                 
260                 DXGI_FORMAT_BC2_TYPELESS = 73,
261                 DXGI_FORMAT_BC2_UNORM = 74,
262                 DXGI_FORMAT_BC2_UNORM_SRGB = 75,
263                 
264                 DXGI_FORMAT_BC3_TYPELESS = 76,
265                 DXGI_FORMAT_BC3_UNORM = 77,
266                 DXGI_FORMAT_BC3_UNORM_SRGB = 78,
267                 
268                 DXGI_FORMAT_BC4_TYPELESS = 79,
269                 DXGI_FORMAT_BC4_UNORM = 80,
270                 DXGI_FORMAT_BC4_SNORM = 81,
271                 
272                 DXGI_FORMAT_BC5_TYPELESS = 82,
273                 DXGI_FORMAT_BC5_UNORM = 83,
274                 DXGI_FORMAT_BC5_SNORM = 84,
275                 
276                 DXGI_FORMAT_B5G6R5_UNORM = 85,
277                 DXGI_FORMAT_B5G5R5A1_UNORM = 86,
278                 DXGI_FORMAT_B8G8R8A8_UNORM = 87,
279                 DXGI_FORMAT_B8G8R8X8_UNORM = 88,
280         };
281
282         enum D3D10_RESOURCE_DIMENSION
283         {
284                 D3D10_RESOURCE_DIMENSION_UNKNOWN = 0,
285                 D3D10_RESOURCE_DIMENSION_BUFFER = 1,
286                 D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2,
287                 D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3,
288                 D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4,
289         };
290
291
292         const char * getDxgiFormatString(DXGI_FORMAT dxgiFormat)
293         {
294 #define CASE(format) case DXGI_FORMAT_##format: return #format
295                 switch(dxgiFormat)
296                 {
297                         CASE(UNKNOWN);
298                         
299                         CASE(R32G32B32A32_TYPELESS);
300                         CASE(R32G32B32A32_FLOAT);
301                         CASE(R32G32B32A32_UINT);
302                         CASE(R32G32B32A32_SINT);
303                         
304                         CASE(R32G32B32_TYPELESS);
305                         CASE(R32G32B32_FLOAT);
306                         CASE(R32G32B32_UINT);
307                         CASE(R32G32B32_SINT);
308                         
309                         CASE(R16G16B16A16_TYPELESS);
310                         CASE(R16G16B16A16_FLOAT);
311                         CASE(R16G16B16A16_UNORM);
312                         CASE(R16G16B16A16_UINT);
313                         CASE(R16G16B16A16_SNORM);
314                         CASE(R16G16B16A16_SINT);
315                         
316                         CASE(R32G32_TYPELESS);
317                         CASE(R32G32_FLOAT);
318                         CASE(R32G32_UINT);
319                         CASE(R32G32_SINT);
320                         
321                         CASE(R32G8X24_TYPELESS);
322                         CASE(D32_FLOAT_S8X24_UINT);
323                         CASE(R32_FLOAT_X8X24_TYPELESS);
324                         CASE(X32_TYPELESS_G8X24_UINT);
325                         
326                         CASE(R10G10B10A2_TYPELESS);
327                         CASE(R10G10B10A2_UNORM);
328                         CASE(R10G10B10A2_UINT);
329                         
330                         CASE(R11G11B10_FLOAT);
331                         
332                         CASE(R8G8B8A8_TYPELESS);
333                         CASE(R8G8B8A8_UNORM);
334                         CASE(R8G8B8A8_UNORM_SRGB);
335                         CASE(R8G8B8A8_UINT);
336                         CASE(R8G8B8A8_SNORM);
337                         CASE(R8G8B8A8_SINT);
338                         
339                         CASE(R16G16_TYPELESS);
340                         CASE(R16G16_FLOAT);
341                         CASE(R16G16_UNORM);
342                         CASE(R16G16_UINT);
343                         CASE(R16G16_SNORM);
344                         CASE(R16G16_SINT);
345                         
346                         CASE(R32_TYPELESS);
347                         CASE(D32_FLOAT);
348                         CASE(R32_FLOAT);
349                         CASE(R32_UINT);
350                         CASE(R32_SINT);
351                         
352                         CASE(R24G8_TYPELESS);
353                         CASE(D24_UNORM_S8_UINT);
354                         CASE(R24_UNORM_X8_TYPELESS);
355                         CASE(X24_TYPELESS_G8_UINT);
356                         
357                         CASE(R8G8_TYPELESS);
358                         CASE(R8G8_UNORM);
359                         CASE(R8G8_UINT);
360                         CASE(R8G8_SNORM);
361                         CASE(R8G8_SINT);
362                         
363                         CASE(R16_TYPELESS);
364                         CASE(R16_FLOAT);
365                         CASE(D16_UNORM);
366                         CASE(R16_UNORM);
367                         CASE(R16_UINT);
368                         CASE(R16_SNORM);
369                         CASE(R16_SINT);
370                         
371                         CASE(R8_TYPELESS);
372                         CASE(R8_UNORM);
373                         CASE(R8_UINT);
374                         CASE(R8_SNORM);
375                         CASE(R8_SINT);
376                         CASE(A8_UNORM);
377
378                         CASE(R1_UNORM);
379                 
380                         CASE(R9G9B9E5_SHAREDEXP);
381                         
382                         CASE(R8G8_B8G8_UNORM);
383                         CASE(G8R8_G8B8_UNORM);
384
385                         CASE(BC1_TYPELESS);
386                         CASE(BC1_UNORM);
387                         CASE(BC1_UNORM_SRGB);
388                 
389                         CASE(BC2_TYPELESS);
390                         CASE(BC2_UNORM);
391                         CASE(BC2_UNORM_SRGB);
392                 
393                         CASE(BC3_TYPELESS);
394                         CASE(BC3_UNORM);
395                         CASE(BC3_UNORM_SRGB);
396                 
397                         CASE(BC4_TYPELESS);
398                         CASE(BC4_UNORM);
399                         CASE(BC4_SNORM);
400                 
401                         CASE(BC5_TYPELESS);
402                         CASE(BC5_UNORM);
403                         CASE(BC5_SNORM);
404
405                         CASE(B5G6R5_UNORM);
406                         CASE(B5G5R5A1_UNORM);
407                         CASE(B8G8R8A8_UNORM);
408                         CASE(B8G8R8X8_UNORM);
409
410                         default: 
411                                 return "UNKNOWN";
412                 }
413 #undef CASE
414         }
415         
416         const char * getD3d10ResourceDimensionString(D3D10_RESOURCE_DIMENSION resourceDimension)
417         {
418                 switch(resourceDimension)
419                 {
420                         default:
421                         case D3D10_RESOURCE_DIMENSION_UNKNOWN: return "UNKNOWN";
422                         case D3D10_RESOURCE_DIMENSION_BUFFER: return "BUFFER";
423                         case D3D10_RESOURCE_DIMENSION_TEXTURE1D: return "TEXTURE1D";
424                         case D3D10_RESOURCE_DIMENSION_TEXTURE2D: return "TEXTURE2D";
425                         case D3D10_RESOURCE_DIMENSION_TEXTURE3D: return "TEXTURE3D";
426                 }
427         }
428
429 /*** implementation ***/
430
431 void mem_read(Stream & mem, DDSPixelFormat & pf)
432 {
433         mem_read(mem, pf.size);
434         mem_read(mem, pf.flags);
435         mem_read(mem, pf.fourcc);
436         mem_read(mem, pf.bitcount);
437         mem_read(mem, pf.rmask);
438         mem_read(mem, pf.gmask);
439         mem_read(mem, pf.bmask);
440         mem_read(mem, pf.amask);
441 }
442
443 void mem_read(Stream & mem, DDSCaps & caps)
444 {
445         mem_read(mem, caps.caps1);
446         mem_read(mem, caps.caps2);
447         mem_read(mem, caps.caps3);
448         mem_read(mem, caps.caps4);
449 }
450
451 void mem_read(Stream & mem, DDSHeader10 & header)
452 {
453         mem_read(mem, header.dxgiFormat);
454         mem_read(mem, header.resourceDimension);
455         mem_read(mem, header.miscFlag);
456         mem_read(mem, header.arraySize);
457         mem_read(mem, header.reserved);
458 }
459
460 void mem_read(Stream & mem, DDSHeader & header)
461 {
462         mem_read(mem, header.fourcc);
463         mem_read(mem, header.size);
464         mem_read(mem, header.flags);
465         mem_read(mem, header.height);
466         mem_read(mem, header.width);
467         mem_read(mem, header.pitch);
468         mem_read(mem, header.depth);
469         mem_read(mem, header.mipmapcount);
470         for (uint i = 0; i < 11; i++) mem_read(mem, header.reserved[i]);
471         mem_read(mem, header.pf);
472         mem_read(mem, header.caps);
473         mem_read(mem, header.notused);
474
475         if (header.hasDX10Header())
476         {
477                 mem_read(mem, header.header10);
478         }
479 }
480
481
482
483 DDSHeader::DDSHeader()
484 {
485         this->fourcc = FOURCC_DDS;
486         this->size = 124;
487         this->flags  = (DDSD_CAPS|DDSD_PIXELFORMAT);
488         this->height = 0;
489         this->width = 0;
490         this->pitch = 0;
491         this->depth = 0;
492         this->mipmapcount = 0;
493         for (uint i = 0; i < 11; i++) this->reserved[i] = 0;
494
495         // Store version information on the reserved header attributes.
496         this->reserved[9] = MAKEFOURCC('N', 'V', 'T', 'T');
497         this->reserved[10] = (0 << 16) | (9 << 8) | (5);        // major.minor.revision
498
499         this->pf.size = 32;
500         this->pf.flags = 0;
501         this->pf.fourcc = 0;
502         this->pf.bitcount = 0;
503         this->pf.rmask = 0;
504         this->pf.gmask = 0;
505         this->pf.bmask = 0;
506         this->pf.amask = 0;
507         this->caps.caps1 = DDSCAPS_TEXTURE;
508         this->caps.caps2 = 0;
509         this->caps.caps3 = 0;
510         this->caps.caps4 = 0;
511         this->notused = 0;
512
513         this->header10.dxgiFormat = DXGI_FORMAT_UNKNOWN;
514         this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_UNKNOWN;
515         this->header10.miscFlag = 0;
516         this->header10.arraySize = 0;
517         this->header10.reserved = 0;
518 }
519
520 void DDSHeader::setWidth(uint w)
521 {
522         this->flags |= DDSD_WIDTH;
523         this->width = w;
524 }
525
526 void DDSHeader::setHeight(uint h)
527 {
528         this->flags |= DDSD_HEIGHT;
529         this->height = h;
530 }
531
532 void DDSHeader::setDepth(uint d)
533 {
534         this->flags |= DDSD_DEPTH;
535         this->height = d;
536 }
537
538 void DDSHeader::setMipmapCount(uint count)
539 {
540         if (count == 0 || count == 1)
541         {
542                 this->flags &= ~DDSD_MIPMAPCOUNT;
543                 this->mipmapcount = 0;
544
545                 if (this->caps.caps2 == 0) {
546                         this->caps.caps1 = DDSCAPS_TEXTURE;
547                 }
548                 else {
549                         this->caps.caps1 = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
550                 }
551         }
552         else
553         {
554                 this->flags |= DDSD_MIPMAPCOUNT;
555                 this->mipmapcount = count;
556
557                 this->caps.caps1 |= DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
558         }
559 }
560
561 void DDSHeader::setTexture2D()
562 {
563         this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
564 }
565
566 void DDSHeader::setTexture3D()
567 {
568         this->caps.caps2 = DDSCAPS2_VOLUME;
569
570         this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D;
571 }
572
573 void DDSHeader::setTextureCube()
574 {
575         this->caps.caps1 |= DDSCAPS_COMPLEX;
576         this->caps.caps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALL_FACES;
577
578         this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
579         this->header10.arraySize = 6;
580 }
581
582 void DDSHeader::setLinearSize(uint size)
583 {
584         this->flags &= ~DDSD_PITCH;
585         this->flags |= DDSD_LINEARSIZE;
586         this->pitch = size;
587 }
588
589 void DDSHeader::setPitch(uint pitch)
590 {
591         this->flags &= ~DDSD_LINEARSIZE;
592         this->flags |= DDSD_PITCH;
593         this->pitch = pitch;
594 }
595
596 void DDSHeader::setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3)
597 {
598         // set fourcc pixel format.
599         this->pf.flags = DDPF_FOURCC;
600         this->pf.fourcc = MAKEFOURCC(c0, c1, c2, c3);
601
602         if (this->pf.fourcc == FOURCC_ATI2)
603         {
604                 this->pf.bitcount = FOURCC_A2XY;
605         }
606         else
607         {
608                 this->pf.bitcount = 0;
609         }
610         
611         this->pf.rmask = 0;
612         this->pf.gmask = 0;
613         this->pf.bmask = 0;
614         this->pf.amask = 0;
615 }
616
617 void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
618 {
619         // Make sure the masks are correct.
620         if ((rmask & gmask) || \
621                 (rmask & bmask) || \
622                 (rmask & amask) || \
623                 (gmask & bmask) || \
624                 (gmask & amask) || \
625                 (bmask & amask)) {
626                 printf("DDS: bad RGBA masks, pixel format not set\n");
627                 return;
628         }
629
630         this->pf.flags = DDPF_RGB;
631
632         if (amask != 0) {
633                 this->pf.flags |= DDPF_ALPHAPIXELS;
634         }
635
636         if (bitcount == 0)
637         {
638                 // Compute bit count from the masks.
639                 uint total = rmask | gmask | bmask | amask;
640                 while(total != 0) {
641                         bitcount++;
642                         total >>= 1;
643                 }
644         }
645
646         if (!(bitcount > 0 && bitcount <= 32)) {
647                 printf("DDS: bad bit count, pixel format not set\n");
648                 return;
649         }
650
651         // Align to 8.
652         if (bitcount <= 8) bitcount = 8;
653         else if (bitcount <= 16) bitcount = 16;
654         else if (bitcount <= 24) bitcount = 24;
655         else bitcount = 32;
656
657         this->pf.fourcc = 0; //findD3D9Format(bitcount, rmask, gmask, bmask, amask);
658         this->pf.bitcount = bitcount;
659         this->pf.rmask = rmask;
660         this->pf.gmask = gmask;
661         this->pf.bmask = bmask;
662         this->pf.amask = amask;
663 }
664
665 void DDSHeader::setDX10Format(uint format)
666 {
667         //this->pf.flags = 0;
668         this->pf.fourcc = FOURCC_DX10;
669         this->header10.dxgiFormat = format;
670 }
671
672 void DDSHeader::setNormalFlag(bool b)
673 {
674         if (b) this->pf.flags |= DDPF_NORMAL;
675         else this->pf.flags &= ~DDPF_NORMAL;
676 }
677
678 bool DDSHeader::hasDX10Header() const
679 {
680         return this->pf.fourcc == FOURCC_DX10;  // @@ This is according to AMD
681         //return this->pf.flags == 0;             // @@ This is according to MS
682 }
683
684 DirectDrawSurface::DirectDrawSurface(unsigned char *mem, uint size) : stream(mem, size), header()
685 {
686         mem_read(stream, header);
687
688         // some ATI2 compressed normal maps do not have their
689         // normal flag set, so force it here (the original nvtt don't do
690         // this, but the decompressor has a -forcenormal flag)
691         if (header.pf.fourcc == FOURCC_ATI2) header.setNormalFlag(true);
692 }
693
694 DirectDrawSurface::~DirectDrawSurface()
695 {
696 }
697
698 bool DirectDrawSurface::isValid() const
699 {
700         if (header.fourcc != FOURCC_DDS || header.size != 124)
701         {
702                 return false;
703         }
704         
705         const uint required = (DDSD_WIDTH|DDSD_HEIGHT/*|DDSD_CAPS|DDSD_PIXELFORMAT*/);
706         if( (header.flags & required) != required ) {
707                 return false;
708         }
709         
710         if (header.pf.size != 32) {
711                 return false;
712         }
713
714         /* in some files DDSCAPS_TEXTURE is missing: silently ignore */
715         /*
716         if( !(header.caps.caps1 & DDSCAPS_TEXTURE) ) {
717                 return false;
718         }
719         */
720
721         return true;
722 }
723
724 bool DirectDrawSurface::isSupported() const
725 {
726         if (header.hasDX10Header())
727         {
728         }
729         else
730         {
731                 if (header.pf.flags & DDPF_FOURCC)
732                 {
733                         if (header.pf.fourcc != FOURCC_DXT1 &&
734                             header.pf.fourcc != FOURCC_DXT2 &&
735                             header.pf.fourcc != FOURCC_DXT3 &&
736                             header.pf.fourcc != FOURCC_DXT4 &&
737                             header.pf.fourcc != FOURCC_DXT5 &&
738                             header.pf.fourcc != FOURCC_RXGB &&
739                             header.pf.fourcc != FOURCC_ATI1 &&
740                             header.pf.fourcc != FOURCC_ATI2)
741                         {
742                                 // Unknown fourcc code.
743                                 return false;
744                         }
745                 }
746                 else if (header.pf.flags & DDPF_RGB)
747                 {
748                         // All RGB formats are supported now.
749                 }
750                 else
751                 {
752                         return false;
753                 }
754                 
755                 if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES)
756                 {
757                         // Cubemaps must contain all faces.
758                         return false;
759                 }
760         
761                 if (isTexture3D())
762                 {
763                         // @@ 3D textures not supported yet.
764                         return false;
765                 }
766         }
767         
768         return true;
769 }
770
771
772 uint DirectDrawSurface::mipmapCount() const
773 {
774         if (header.flags & DDSD_MIPMAPCOUNT) return header.mipmapcount;
775         else return 1;
776 }
777
778
779 uint DirectDrawSurface::width() const
780 {
781         if (header.flags & DDSD_WIDTH) return header.width;
782         else return 1;
783 }
784
785 uint DirectDrawSurface::height() const
786 {
787         if (header.flags & DDSD_HEIGHT) return header.height;
788         else return 1;
789 }
790
791 uint DirectDrawSurface::depth() const
792 {
793         if (header.flags & DDSD_DEPTH) return header.depth;
794         else return 1;
795 }
796
797 bool DirectDrawSurface::hasAlpha() const
798 {
799         if ((header.pf.flags & DDPF_RGB) && (header.pf.amask == 0))
800         {
801                 return false;
802         }
803         else if (header.pf.fourcc == FOURCC_DXT1)
804         {
805                 return false;
806         }
807         else
808         {
809                 return true;
810         }
811 }
812
813 bool DirectDrawSurface::isTexture1D() const
814 {
815         if (header.hasDX10Header())
816         {
817                 return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE1D;
818         }
819         return false;
820 }
821
822 bool DirectDrawSurface::isTexture2D() const
823 {
824         if (header.hasDX10Header())
825         {
826                 return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE2D;
827         }
828         else
829         {
830                 return !isTexture3D() && !isTextureCube();
831         }
832 }
833
834 bool DirectDrawSurface::isTexture3D() const
835 {
836         if (header.hasDX10Header())
837         {
838                 return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE3D;
839         }
840         else
841         {
842         return (header.caps.caps2 & DDSCAPS2_VOLUME) != 0;
843         }
844 }
845
846 bool DirectDrawSurface::isTextureCube() const
847 {
848         return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0;
849 }
850
851 void DirectDrawSurface::setNormalFlag(bool b)
852 {
853         header.setNormalFlag(b);
854 }
855
856 void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap)
857 {
858         stream.seek(offset(face, mipmap));
859         
860         uint w = width();
861         uint h = height();
862         
863         // Compute width and height.
864         for (uint m = 0; m < mipmap; m++)
865         {
866                 w = max(1U, w / 2);
867                 h = max(1U, h / 2);
868         }
869         
870         img->allocate(w, h);
871         
872         if (header.pf.flags & DDPF_RGB) 
873         {
874                 readLinearImage(img);
875         }
876         else if (header.pf.flags & DDPF_FOURCC)
877         {
878                 readBlockImage(img);
879         }
880 }
881
882 void DirectDrawSurface::readLinearImage(Image * img)
883 {
884         
885         const uint w = img->width();
886         const uint h = img->height();
887         
888         uint rshift, rsize;
889         PixelFormat::maskShiftAndSize(header.pf.rmask, &rshift, &rsize);
890         
891         uint gshift, gsize;
892         PixelFormat::maskShiftAndSize(header.pf.gmask, &gshift, &gsize);
893         
894         uint bshift, bsize;
895         PixelFormat::maskShiftAndSize(header.pf.bmask, &bshift, &bsize);
896         
897         uint ashift, asize;
898         PixelFormat::maskShiftAndSize(header.pf.amask, &ashift, &asize);
899
900         uint byteCount = (header.pf.bitcount + 7) / 8;
901
902         if (byteCount > 4)
903         {
904                 /* just in case... we could have segfaults later on if byteCount > 4 */
905                 printf("DDS: bitcount too large");
906                 return;
907         }
908
909         // set image format: RGB or ARGB
910         // alpha channel exists if and only if the alpha mask is non-zero
911         if (header.pf.amask == 0)
912         {
913                 img->setFormat(Image::Format_RGB);
914         }
915         else
916         {
917                 img->setFormat(Image::Format_ARGB);
918         }
919
920         // Read linear RGB images.
921         for (uint y = 0; y < h; y++)
922         {
923                 for (uint x = 0; x < w; x++)
924                 {
925                         uint c = 0;
926                         mem_read(stream, (unsigned char *)(&c), byteCount);
927
928                         Color32 pixel(0, 0, 0, 0xFF);
929                         pixel.r = PixelFormat::convert(c >> rshift, rsize, 8);
930                         pixel.g = PixelFormat::convert(c >> gshift, gsize, 8);
931                         pixel.b = PixelFormat::convert(c >> bshift, bsize, 8);
932                         pixel.a = PixelFormat::convert(c >> ashift, asize, 8);
933
934                         img->pixel(x, y) = pixel;
935                 }
936         }
937 }
938
939 void DirectDrawSurface::readBlockImage(Image * img)
940 {
941
942         // set image format: RGB or ARGB
943         if (header.pf.fourcc == FOURCC_RXGB ||
944                 header.pf.fourcc == FOURCC_ATI1 ||
945                 header.pf.fourcc == FOURCC_ATI2 ||
946                 header.pf.flags & DDPF_NORMAL)
947         {
948                 img->setFormat(Image::Format_RGB);
949         }
950         else
951         {
952                 img->setFormat(Image::Format_ARGB);
953         }
954
955         const uint w = img->width();
956         const uint h = img->height();
957         
958         const uint bw = (w + 3) / 4;
959         const uint bh = (h + 3) / 4;
960         
961         for (uint by = 0; by < bh; by++)
962         {
963                 for (uint bx = 0; bx < bw; bx++)
964                 {
965                         ColorBlock block;
966                         
967                         // Read color block.
968                         readBlock(&block);
969                         
970                         // Write color block.
971                         for (uint y = 0; y < min(4U, h-4*by); y++)
972                         {
973                                 for (uint x = 0; x < min(4U, w-4*bx); x++)
974                                 {
975                                         img->pixel(4*bx+x, 4*by+y) = block.color(x, y);
976                                 }
977                         }
978                 }
979         }
980 }
981
982 static Color32 buildNormal(uint8 x, uint8 y)
983 {
984         float nx = 2 * (x / 255.0f) - 1;
985         float ny = 2 * (y / 255.0f) - 1;
986         float nz = 0.0f;
987         if (1 - nx*nx - ny*ny > 0) nz = sqrt(1 - nx*nx - ny*ny);
988         uint8 z = clamp(int(255.0f * (nz + 1) / 2.0f), 0, 255);
989         
990         return Color32(x, y, z);
991 }
992
993
994 void DirectDrawSurface::readBlock(ColorBlock * rgba)
995 {
996         if (header.pf.fourcc == FOURCC_DXT1)
997         {
998                 BlockDXT1 block;
999                 mem_read(stream, block);
1000                 block.decodeBlock(rgba);
1001         }
1002         else if (header.pf.fourcc == FOURCC_DXT2 ||
1003             header.pf.fourcc == FOURCC_DXT3)
1004         {
1005                 BlockDXT3 block;
1006                 mem_read(stream, block);
1007                 block.decodeBlock(rgba);
1008         }
1009         else if (header.pf.fourcc == FOURCC_DXT4 ||
1010             header.pf.fourcc == FOURCC_DXT5 ||
1011             header.pf.fourcc == FOURCC_RXGB)
1012         {
1013                 BlockDXT5 block;
1014                 mem_read(stream, block);
1015                 block.decodeBlock(rgba);
1016                 
1017                 if (header.pf.fourcc == FOURCC_RXGB)
1018                 {
1019                         // Swap R & A.
1020                         for (int i = 0; i < 16; i++)
1021                         {
1022                                 Color32 & c = rgba->color(i);
1023                                 uint tmp = c.r;
1024                                 c.r = c.a;
1025                                 c.a = tmp;
1026                         }
1027                 }
1028         }
1029         else if (header.pf.fourcc == FOURCC_ATI1)
1030         {
1031                 BlockATI1 block;
1032                 mem_read(stream, block);
1033                 block.decodeBlock(rgba);
1034         }
1035         else if (header.pf.fourcc == FOURCC_ATI2)
1036         {
1037                 BlockATI2 block;
1038                 mem_read(stream, block);
1039                 block.decodeBlock(rgba);
1040         }
1041         
1042         // If normal flag set, convert to normal.
1043         if (header.pf.flags & DDPF_NORMAL)
1044         {
1045                 if (header.pf.fourcc == FOURCC_ATI2)
1046                 {
1047                         for (int i = 0; i < 16; i++)
1048                         {
1049                                 Color32 & c = rgba->color(i);
1050                                 c = buildNormal(c.r, c.g);
1051                         }
1052                 }
1053                 else if (header.pf.fourcc == FOURCC_DXT5)
1054                 {
1055                         for (int i = 0; i < 16; i++)
1056                         {
1057                                 Color32 & c = rgba->color(i);
1058                                 c = buildNormal(c.a, c.g);
1059                         }
1060                 }
1061         }
1062 }
1063
1064
1065 uint DirectDrawSurface::blockSize() const
1066 {
1067         switch(header.pf.fourcc)
1068         {
1069                 case FOURCC_DXT1:
1070                 case FOURCC_ATI1:
1071                         return 8;
1072                 case FOURCC_DXT2:
1073                 case FOURCC_DXT3:
1074                 case FOURCC_DXT4:
1075                 case FOURCC_DXT5:
1076                 case FOURCC_RXGB:
1077                 case FOURCC_ATI2:
1078                         return 16;
1079         };
1080
1081         // Not a block image.
1082         return 0;
1083 }
1084
1085 uint DirectDrawSurface::mipmapSize(uint mipmap) const
1086 {
1087         uint w = width();
1088         uint h = height();
1089         uint d = depth();
1090         
1091         for (uint m = 0; m < mipmap; m++)
1092         {
1093                 w = max(1U, w / 2);
1094                 h = max(1U, h / 2);
1095                 d = max(1U, d / 2);
1096         }
1097
1098         if (header.pf.flags & DDPF_FOURCC)
1099         {
1100                 // @@ How are 3D textures aligned?
1101                 w = (w + 3) / 4;
1102                 h = (h + 3) / 4;
1103                 return blockSize() * w * h;
1104         }
1105         else if (header.pf.flags & DDPF_RGB)
1106         {
1107                 // Align pixels to bytes.
1108                 uint byteCount = (header.pf.bitcount + 7) / 8;
1109                 
1110                 // Align pitch to 4 bytes.
1111                 uint pitch = 4 * ((w * byteCount + 3) / 4);
1112                 
1113                 return pitch * h * d;
1114         }
1115         else {
1116                 printf("DDS: mipmap format not supported\n");
1117                 return(0);
1118         };
1119 }
1120
1121 uint DirectDrawSurface::faceSize() const
1122 {
1123         const uint count = mipmapCount();
1124         uint size = 0;
1125         
1126         for (uint m = 0; m < count; m++)
1127         {
1128                 size += mipmapSize(m);
1129         }
1130         
1131         return size;
1132 }
1133
1134 uint DirectDrawSurface::offset(const uint face, const uint mipmap)
1135 {
1136         uint size = 128; //sizeof(DDSHeader);
1137         
1138         if (header.hasDX10Header())
1139         {
1140                 size += 20; // sizeof(DDSHeader10);
1141         }
1142
1143         if (face != 0)
1144         {
1145                 size += face * faceSize();
1146         }
1147         
1148         for (uint m = 0; m < mipmap; m++)
1149         {
1150                 size += mipmapSize(m);
1151         }
1152         
1153         return size;
1154 }
1155
1156
1157 void DirectDrawSurface::printInfo() const
1158 {
1159         /* printf("FOURCC: %c%c%c%c\n", ((unsigned char *)&header.fourcc)[0], ((unsigned char *)&header.fourcc)[1], ((unsigned char *)&header.fourcc)[2], ((unsigned char *)&header.fourcc)[3]); */
1160         printf("Flags: 0x%.8X\n", header.flags);
1161         if (header.flags & DDSD_CAPS) printf("\tDDSD_CAPS\n");
1162         if (header.flags & DDSD_PIXELFORMAT) printf("\tDDSD_PIXELFORMAT\n");
1163         if (header.flags & DDSD_WIDTH) printf("\tDDSD_WIDTH\n");
1164         if (header.flags & DDSD_HEIGHT) printf("\tDDSD_HEIGHT\n");
1165         if (header.flags & DDSD_DEPTH) printf("\tDDSD_DEPTH\n");
1166         if (header.flags & DDSD_PITCH) printf("\tDDSD_PITCH\n");
1167         if (header.flags & DDSD_LINEARSIZE) printf("\tDDSD_LINEARSIZE\n");
1168         if (header.flags & DDSD_MIPMAPCOUNT) printf("\tDDSD_MIPMAPCOUNT\n");
1169
1170         printf("Height: %d\n", header.height);
1171         printf("Width: %d\n", header.width);
1172         printf("Depth: %d\n", header.depth);
1173         if (header.flags & DDSD_PITCH) printf("Pitch: %d\n", header.pitch);
1174         else if (header.flags & DDSD_LINEARSIZE) printf("Linear size: %d\n", header.pitch);
1175         printf("Mipmap count: %d\n", header.mipmapcount);
1176         
1177         printf("Pixel Format:\n");
1178         /* printf("\tSize: %d\n", header.pf.size); */
1179         printf("\tFlags: 0x%.8X\n", header.pf.flags);
1180         if (header.pf.flags & DDPF_RGB) printf("\t\tDDPF_RGB\n");
1181         if (header.pf.flags & DDPF_FOURCC) printf("\t\tDDPF_FOURCC\n");
1182         if (header.pf.flags & DDPF_ALPHAPIXELS) printf("\t\tDDPF_ALPHAPIXELS\n");
1183         if (header.pf.flags & DDPF_ALPHA) printf("\t\tDDPF_ALPHA\n");
1184         if (header.pf.flags & DDPF_PALETTEINDEXED1) printf("\t\tDDPF_PALETTEINDEXED1\n");
1185         if (header.pf.flags & DDPF_PALETTEINDEXED2) printf("\t\tDDPF_PALETTEINDEXED2\n");
1186         if (header.pf.flags & DDPF_PALETTEINDEXED4) printf("\t\tDDPF_PALETTEINDEXED4\n");
1187         if (header.pf.flags & DDPF_PALETTEINDEXED8) printf("\t\tDDPF_PALETTEINDEXED8\n");
1188         if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n");
1189         if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n");
1190         
1191         printf("\tFourCC: '%c%c%c%c'\n",
1192                 ((header.pf.fourcc >> 0) & 0xFF),
1193                 ((header.pf.fourcc >> 8) & 0xFF),
1194                 ((header.pf.fourcc >> 16) & 0xFF),
1195                 ((header.pf.fourcc >> 24) & 0xFF));
1196         if ((header.pf.fourcc & DDPF_FOURCC) && (header.pf.bitcount != 0))
1197         {
1198                 printf("\tSwizzle: '%c%c%c%c'\n", 
1199                         (header.pf.bitcount >> 0) & 0xFF,
1200                         (header.pf.bitcount >> 8) & 0xFF,
1201                         (header.pf.bitcount >> 16) & 0xFF,
1202                         (header.pf.bitcount >> 24) & 0xFF);
1203         }
1204         else
1205         {
1206                 printf("\tBit count: %d\n", header.pf.bitcount);
1207         }
1208         printf("\tRed mask: 0x%.8X\n", header.pf.rmask);
1209         printf("\tGreen mask: 0x%.8X\n", header.pf.gmask);
1210         printf("\tBlue mask: 0x%.8X\n", header.pf.bmask);
1211         printf("\tAlpha mask: 0x%.8X\n", header.pf.amask);
1212
1213         printf("Caps:\n");
1214         printf("\tCaps 1: 0x%.8X\n", header.caps.caps1);
1215         if (header.caps.caps1 & DDSCAPS_COMPLEX) printf("\t\tDDSCAPS_COMPLEX\n");
1216         if (header.caps.caps1 & DDSCAPS_TEXTURE) printf("\t\tDDSCAPS_TEXTURE\n");
1217         if (header.caps.caps1 & DDSCAPS_MIPMAP) printf("\t\tDDSCAPS_MIPMAP\n");
1218
1219         printf("\tCaps 2: 0x%.8X\n", header.caps.caps2);
1220         if (header.caps.caps2 & DDSCAPS2_VOLUME) printf("\t\tDDSCAPS2_VOLUME\n");
1221         else if (header.caps.caps2 & DDSCAPS2_CUBEMAP)
1222         {
1223                 printf("\t\tDDSCAPS2_CUBEMAP\n");
1224                 if ((header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) == DDSCAPS2_CUBEMAP_ALL_FACES) printf("\t\tDDSCAPS2_CUBEMAP_ALL_FACES\n");
1225                 else {
1226                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEX\n");
1227                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEX\n");
1228                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEY\n");
1229                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEY\n");
1230                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEZ\n");
1231                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEZ\n");
1232                 }
1233         }
1234
1235         printf("\tCaps 3: 0x%.8X\n", header.caps.caps3);
1236         printf("\tCaps 4: 0x%.8X\n", header.caps.caps4);
1237
1238         if (header.hasDX10Header())
1239         {
1240                 printf("DX10 Header:\n");
1241                 printf("\tDXGI Format: %u (%s)\n", header.header10.dxgiFormat, getDxgiFormatString((DXGI_FORMAT)header.header10.dxgiFormat));
1242                 printf("\tResource dimension: %u (%s)\n", header.header10.resourceDimension, getD3d10ResourceDimensionString((D3D10_RESOURCE_DIMENSION)header.header10.resourceDimension));
1243                 printf("\tMisc flag: %u\n", header.header10.miscFlag);
1244                 printf("\tArray size: %u\n", header.header10.arraySize);
1245         }
1246         
1247         if (header.reserved[9] == MAKEFOURCC('N', 'V', 'T', 'T'))
1248         {
1249                 int major = (header.reserved[10] >> 16) & 0xFF;
1250                 int minor = (header.reserved[10] >> 8) & 0xFF;
1251                 int revision= header.reserved[10] & 0xFF;
1252                 
1253                 printf("Version:\n");
1254                 printf("\tNVIDIA Texture Tools %d.%d.%d\n", major, minor, revision);
1255         }
1256 }
1257