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