2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * Contributors: Amorilia (amorilia@users.sourceforge.net)
20 * ***** END GPL LICENSE BLOCK *****
23 /** \file blender/imbuf/intern/dds/DirectDrawSurface.cpp
29 * This file is based on a similar file from the NVIDIA texture tools
30 * (http://nvidia-texture-tools.googlecode.com/)
32 * Original license from NVIDIA follows.
35 // Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
37 // Permission is hereby granted, free of charge, to any person
38 // obtaining a copy of this software and associated documentation
39 // files (the "Software"), to deal in the Software without
40 // restriction, including without limitation the rights to use,
41 // copy, modify, merge, publish, distribute, sublicense, and/or sell
42 // copies of the Software, and to permit persons to whom the
43 // Software is furnished to do so, subject to the following
46 // The above copyright notice and this permission notice shall be
47 // included in all copies or substantial portions of the Software.
49 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
50 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
51 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
52 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
53 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
54 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
55 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
56 // OTHER DEALINGS IN THE SOFTWARE.
58 #include <DirectDrawSurface.h>
60 #include <PixelFormat.h>
62 #include <stdio.h> // printf
63 #include <math.h> // sqrt
64 #include <sys/types.h>
66 /*** declarations ***/
68 #if !defined(MAKEFOURCC)
69 # define MAKEFOURCC(ch0, ch1, ch2, ch3) \
70 (uint(uint8(ch0)) | (uint(uint8(ch1)) << 8) | \
71 (uint(uint8(ch2)) << 16) | (uint(uint8(ch3)) << 24 ))
74 static const uint FOURCC_NVTT = MAKEFOURCC('N', 'V', 'T', 'T');
75 static const uint FOURCC_DDS = MAKEFOURCC('D', 'D', 'S', ' ');
76 static const uint FOURCC_DXT1 = MAKEFOURCC('D', 'X', 'T', '1');
77 static const uint FOURCC_DXT2 = MAKEFOURCC('D', 'X', 'T', '2');
78 static const uint FOURCC_DXT3 = MAKEFOURCC('D', 'X', 'T', '3');
79 static const uint FOURCC_DXT4 = MAKEFOURCC('D', 'X', 'T', '4');
80 static const uint FOURCC_DXT5 = MAKEFOURCC('D', 'X', 'T', '5');
81 static const uint FOURCC_RXGB = MAKEFOURCC('R', 'X', 'G', 'B');
82 static const uint FOURCC_ATI1 = MAKEFOURCC('A', 'T', 'I', '1');
83 static const uint FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2');
85 static const uint FOURCC_A2XY = MAKEFOURCC('A', '2', 'X', 'Y');
87 static const uint FOURCC_DX10 = MAKEFOURCC('D', 'X', '1', '0');
89 static const uint FOURCC_UVER = MAKEFOURCC('U', 'V', 'E', 'R');
91 // 32 bit RGB formats.
92 static const uint D3DFMT_R8G8B8 = 20;
93 static const uint D3DFMT_A8R8G8B8 = 21;
94 static const uint D3DFMT_X8R8G8B8 = 22;
95 static const uint D3DFMT_R5G6B5 = 23;
96 static const uint D3DFMT_X1R5G5B5 = 24;
97 static const uint D3DFMT_A1R5G5B5 = 25;
98 static const uint D3DFMT_A4R4G4B4 = 26;
99 static const uint D3DFMT_R3G3B2 = 27;
100 static const uint D3DFMT_A8 = 28;
101 static const uint D3DFMT_A8R3G3B2 = 29;
102 static const uint D3DFMT_X4R4G4B4 = 30;
103 static const uint D3DFMT_A2B10G10R10 = 31;
104 static const uint D3DFMT_A8B8G8R8 = 32;
105 static const uint D3DFMT_X8B8G8R8 = 33;
106 static const uint D3DFMT_G16R16 = 34;
107 static const uint D3DFMT_A2R10G10B10 = 35;
109 static const uint D3DFMT_A16B16G16R16 = 36;
112 static const uint D3DFMT_A8P8 = 40;
113 static const uint D3DFMT_P8 = 41;
115 // Luminance formats.
116 static const uint D3DFMT_L8 = 50;
117 static const uint D3DFMT_A8L8 = 51;
118 static const uint D3DFMT_A4L4 = 52;
119 static const uint D3DFMT_L16 = 81;
121 // Floating point formats
122 static const uint D3DFMT_R16F = 111;
123 static const uint D3DFMT_G16R16F = 112;
124 static const uint D3DFMT_A16B16G16R16F = 113;
125 static const uint D3DFMT_R32F = 114;
126 static const uint D3DFMT_G32R32F = 115;
127 static const uint D3DFMT_A32B32G32R32F = 116;
129 static const uint DDSD_CAPS = 0x00000001U;
130 static const uint DDSD_PIXELFORMAT = 0x00001000U;
131 static const uint DDSD_WIDTH = 0x00000004U;
132 static const uint DDSD_HEIGHT = 0x00000002U;
133 static const uint DDSD_PITCH = 0x00000008U;
134 static const uint DDSD_MIPMAPCOUNT = 0x00020000U;
135 static const uint DDSD_LINEARSIZE = 0x00080000U;
136 static const uint DDSD_DEPTH = 0x00800000U;
138 static const uint DDSCAPS_COMPLEX = 0x00000008U;
139 static const uint DDSCAPS_TEXTURE = 0x00001000U;
140 static const uint DDSCAPS_MIPMAP = 0x00400000U;
141 static const uint DDSCAPS2_VOLUME = 0x00200000U;
142 static const uint DDSCAPS2_CUBEMAP = 0x00000200U;
144 static const uint DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400U;
145 static const uint DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800U;
146 static const uint DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000U;
147 static const uint DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000U;
148 static const uint DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000U;
149 static const uint DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000U;
150 static const uint DDSCAPS2_CUBEMAP_ALL_FACES = 0x0000FC00U;
152 static const uint DDPF_ALPHAPIXELS = 0x00000001U;
153 static const uint DDPF_ALPHA = 0x00000002U;
154 static const uint DDPF_FOURCC = 0x00000004U;
155 static const uint DDPF_RGB = 0x00000040U;
156 static const uint DDPF_PALETTEINDEXED1 = 0x00000800U;
157 static const uint DDPF_PALETTEINDEXED2 = 0x00001000U;
158 static const uint DDPF_PALETTEINDEXED4 = 0x00000008U;
159 static const uint DDPF_PALETTEINDEXED8 = 0x00000020U;
160 static const uint DDPF_LUMINANCE = 0x00020000U;
161 static const uint DDPF_ALPHAPREMULT = 0x00008000U;
163 // Custom NVTT flags.
164 static const uint DDPF_NORMAL = 0x80000000U;
165 static const uint DDPF_SRGB = 0x40000000U;
170 DXGI_FORMAT_UNKNOWN = 0,
172 DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
173 DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
174 DXGI_FORMAT_R32G32B32A32_UINT = 3,
175 DXGI_FORMAT_R32G32B32A32_SINT = 4,
177 DXGI_FORMAT_R32G32B32_TYPELESS = 5,
178 DXGI_FORMAT_R32G32B32_FLOAT = 6,
179 DXGI_FORMAT_R32G32B32_UINT = 7,
180 DXGI_FORMAT_R32G32B32_SINT = 8,
182 DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
183 DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
184 DXGI_FORMAT_R16G16B16A16_UNORM = 11,
185 DXGI_FORMAT_R16G16B16A16_UINT = 12,
186 DXGI_FORMAT_R16G16B16A16_SNORM = 13,
187 DXGI_FORMAT_R16G16B16A16_SINT = 14,
189 DXGI_FORMAT_R32G32_TYPELESS = 15,
190 DXGI_FORMAT_R32G32_FLOAT = 16,
191 DXGI_FORMAT_R32G32_UINT = 17,
192 DXGI_FORMAT_R32G32_SINT = 18,
194 DXGI_FORMAT_R32G8X24_TYPELESS = 19,
195 DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
196 DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
197 DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
199 DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
200 DXGI_FORMAT_R10G10B10A2_UNORM = 24,
201 DXGI_FORMAT_R10G10B10A2_UINT = 25,
203 DXGI_FORMAT_R11G11B10_FLOAT = 26,
205 DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
206 DXGI_FORMAT_R8G8B8A8_UNORM = 28,
207 DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
208 DXGI_FORMAT_R8G8B8A8_UINT = 30,
209 DXGI_FORMAT_R8G8B8A8_SNORM = 31,
210 DXGI_FORMAT_R8G8B8A8_SINT = 32,
212 DXGI_FORMAT_R16G16_TYPELESS = 33,
213 DXGI_FORMAT_R16G16_FLOAT = 34,
214 DXGI_FORMAT_R16G16_UNORM = 35,
215 DXGI_FORMAT_R16G16_UINT = 36,
216 DXGI_FORMAT_R16G16_SNORM = 37,
217 DXGI_FORMAT_R16G16_SINT = 38,
219 DXGI_FORMAT_R32_TYPELESS = 39,
220 DXGI_FORMAT_D32_FLOAT = 40,
221 DXGI_FORMAT_R32_FLOAT = 41,
222 DXGI_FORMAT_R32_UINT = 42,
223 DXGI_FORMAT_R32_SINT = 43,
225 DXGI_FORMAT_R24G8_TYPELESS = 44,
226 DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
227 DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
228 DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
230 DXGI_FORMAT_R8G8_TYPELESS = 48,
231 DXGI_FORMAT_R8G8_UNORM = 49,
232 DXGI_FORMAT_R8G8_UINT = 50,
233 DXGI_FORMAT_R8G8_SNORM = 51,
234 DXGI_FORMAT_R8G8_SINT = 52,
236 DXGI_FORMAT_R16_TYPELESS = 53,
237 DXGI_FORMAT_R16_FLOAT = 54,
238 DXGI_FORMAT_D16_UNORM = 55,
239 DXGI_FORMAT_R16_UNORM = 56,
240 DXGI_FORMAT_R16_UINT = 57,
241 DXGI_FORMAT_R16_SNORM = 58,
242 DXGI_FORMAT_R16_SINT = 59,
244 DXGI_FORMAT_R8_TYPELESS = 60,
245 DXGI_FORMAT_R8_UNORM = 61,
246 DXGI_FORMAT_R8_UINT = 62,
247 DXGI_FORMAT_R8_SNORM = 63,
248 DXGI_FORMAT_R8_SINT = 64,
249 DXGI_FORMAT_A8_UNORM = 65,
251 DXGI_FORMAT_R1_UNORM = 66,
253 DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
255 DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
256 DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
258 DXGI_FORMAT_BC1_TYPELESS = 70,
259 DXGI_FORMAT_BC1_UNORM = 71,
260 DXGI_FORMAT_BC1_UNORM_SRGB = 72,
262 DXGI_FORMAT_BC2_TYPELESS = 73,
263 DXGI_FORMAT_BC2_UNORM = 74,
264 DXGI_FORMAT_BC2_UNORM_SRGB = 75,
266 DXGI_FORMAT_BC3_TYPELESS = 76,
267 DXGI_FORMAT_BC3_UNORM = 77,
268 DXGI_FORMAT_BC3_UNORM_SRGB = 78,
270 DXGI_FORMAT_BC4_TYPELESS = 79,
271 DXGI_FORMAT_BC4_UNORM = 80,
272 DXGI_FORMAT_BC4_SNORM = 81,
274 DXGI_FORMAT_BC5_TYPELESS = 82,
275 DXGI_FORMAT_BC5_UNORM = 83,
276 DXGI_FORMAT_BC5_SNORM = 84,
278 DXGI_FORMAT_B5G6R5_UNORM = 85,
279 DXGI_FORMAT_B5G5R5A1_UNORM = 86,
280 DXGI_FORMAT_B8G8R8A8_UNORM = 87,
281 DXGI_FORMAT_B8G8R8X8_UNORM = 88,
283 DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89,
284 DXGI_FORMAT_B8G8R8A8_TYPELESS = 90,
285 DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91,
286 DXGI_FORMAT_B8G8R8X8_TYPELESS = 92,
287 DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93,
289 DXGI_FORMAT_BC6H_TYPELESS = 94,
290 DXGI_FORMAT_BC6H_UF16 = 95,
291 DXGI_FORMAT_BC6H_SF16 = 96,
293 DXGI_FORMAT_BC7_TYPELESS = 97,
294 DXGI_FORMAT_BC7_UNORM = 98,
295 DXGI_FORMAT_BC7_UNORM_SRGB = 99,
298 enum D3D10_RESOURCE_DIMENSION
300 D3D10_RESOURCE_DIMENSION_UNKNOWN = 0,
301 D3D10_RESOURCE_DIMENSION_BUFFER = 1,
302 D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2,
303 D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3,
304 D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4,
308 static const char * getDxgiFormatString(DXGI_FORMAT dxgiFormat)
310 #define CASE(format) case DXGI_FORMAT_##format: return #format
315 CASE(R32G32B32A32_TYPELESS);
316 CASE(R32G32B32A32_FLOAT);
317 CASE(R32G32B32A32_UINT);
318 CASE(R32G32B32A32_SINT);
320 CASE(R32G32B32_TYPELESS);
321 CASE(R32G32B32_FLOAT);
322 CASE(R32G32B32_UINT);
323 CASE(R32G32B32_SINT);
325 CASE(R16G16B16A16_TYPELESS);
326 CASE(R16G16B16A16_FLOAT);
327 CASE(R16G16B16A16_UNORM);
328 CASE(R16G16B16A16_UINT);
329 CASE(R16G16B16A16_SNORM);
330 CASE(R16G16B16A16_SINT);
332 CASE(R32G32_TYPELESS);
337 CASE(R32G8X24_TYPELESS);
338 CASE(D32_FLOAT_S8X24_UINT);
339 CASE(R32_FLOAT_X8X24_TYPELESS);
340 CASE(X32_TYPELESS_G8X24_UINT);
342 CASE(R10G10B10A2_TYPELESS);
343 CASE(R10G10B10A2_UNORM);
344 CASE(R10G10B10A2_UINT);
346 CASE(R11G11B10_FLOAT);
348 CASE(R8G8B8A8_TYPELESS);
349 CASE(R8G8B8A8_UNORM);
350 CASE(R8G8B8A8_UNORM_SRGB);
352 CASE(R8G8B8A8_SNORM);
355 CASE(R16G16_TYPELESS);
368 CASE(R24G8_TYPELESS);
369 CASE(D24_UNORM_S8_UINT);
370 CASE(R24_UNORM_X8_TYPELESS);
371 CASE(X24_TYPELESS_G8_UINT);
396 CASE(R9G9B9E5_SHAREDEXP);
398 CASE(R8G8_B8G8_UNORM);
399 CASE(G8R8_G8B8_UNORM);
403 CASE(BC1_UNORM_SRGB);
407 CASE(BC2_UNORM_SRGB);
411 CASE(BC3_UNORM_SRGB);
422 CASE(B5G5R5A1_UNORM);
423 CASE(B8G8R8A8_UNORM);
424 CASE(B8G8R8X8_UNORM);
432 static const char * getD3d10ResourceDimensionString(D3D10_RESOURCE_DIMENSION resourceDimension)
434 switch (resourceDimension)
437 case D3D10_RESOURCE_DIMENSION_UNKNOWN: return "UNKNOWN";
438 case D3D10_RESOURCE_DIMENSION_BUFFER: return "BUFFER";
439 case D3D10_RESOURCE_DIMENSION_TEXTURE1D: return "TEXTURE1D";
440 case D3D10_RESOURCE_DIMENSION_TEXTURE2D: return "TEXTURE2D";
441 case D3D10_RESOURCE_DIMENSION_TEXTURE3D: return "TEXTURE3D";
445 /*** implementation ***/
447 void mem_read(Stream & mem, DDSPixelFormat & pf)
449 mem_read(mem, pf.size);
450 mem_read(mem, pf.flags);
451 mem_read(mem, pf.fourcc);
452 mem_read(mem, pf.bitcount);
453 mem_read(mem, pf.rmask);
454 mem_read(mem, pf.gmask);
455 mem_read(mem, pf.bmask);
456 mem_read(mem, pf.amask);
459 void mem_read(Stream & mem, DDSCaps & caps)
461 mem_read(mem, caps.caps1);
462 mem_read(mem, caps.caps2);
463 mem_read(mem, caps.caps3);
464 mem_read(mem, caps.caps4);
467 void mem_read(Stream & mem, DDSHeader10 & header)
469 mem_read(mem, header.dxgiFormat);
470 mem_read(mem, header.resourceDimension);
471 mem_read(mem, header.miscFlag);
472 mem_read(mem, header.arraySize);
473 mem_read(mem, header.reserved);
476 void mem_read(Stream & mem, DDSHeader & header)
478 mem_read(mem, header.fourcc);
479 mem_read(mem, header.size);
480 mem_read(mem, header.flags);
481 mem_read(mem, header.height);
482 mem_read(mem, header.width);
483 mem_read(mem, header.pitch);
484 mem_read(mem, header.depth);
485 mem_read(mem, header.mipmapcount);
486 for (uint i = 0; i < 11; i++) mem_read(mem, header.reserved[i]);
487 mem_read(mem, header.pf);
488 mem_read(mem, header.caps);
489 mem_read(mem, header.notused);
491 if (header.hasDX10Header())
493 mem_read(mem, header.header10);
499 struct FormatDescriptor
509 static const FormatDescriptor s_d3dFormats[] =
511 { D3DFMT_R8G8B8, 24, 0xFF0000, 0xFF00, 0xFF, 0 },
512 { D3DFMT_A8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0xFF000000 }, // DXGI_FORMAT_B8G8R8A8_UNORM
513 { D3DFMT_X8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0 }, // DXGI_FORMAT_B8G8R8X8_UNORM
514 { D3DFMT_R5G6B5, 16, 0xF800, 0x7E0, 0x1F, 0 }, // DXGI_FORMAT_B5G6R5_UNORM
515 { D3DFMT_X1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0 },
516 { D3DFMT_A1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0x8000 }, // DXGI_FORMAT_B5G5R5A1_UNORM
517 { D3DFMT_A4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0xF000 },
518 { D3DFMT_R3G3B2, 8, 0xE0, 0x1C, 0x3, 0 },
519 { D3DFMT_A8, 8, 0, 0, 0, 8 }, // DXGI_FORMAT_A8_UNORM
520 { D3DFMT_A8R3G3B2, 16, 0xE0, 0x1C, 0x3, 0xFF00 },
521 { D3DFMT_X4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0 },
522 { D3DFMT_A2B10G10R10, 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 }, // DXGI_FORMAT_R10G10B10A2
523 { D3DFMT_A8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000 }, // DXGI_FORMAT_R8G8B8A8_UNORM
524 { D3DFMT_X8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0 },
525 { D3DFMT_G16R16, 32, 0xFFFF, 0xFFFF0000, 0, 0 }, // DXGI_FORMAT_R16G16_UNORM
526 { D3DFMT_A2R10G10B10, 32, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000 },
527 { D3DFMT_A2B10G10R10, 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 },
529 { D3DFMT_L8, 8, 8, 0, 0, 0 }, // DXGI_FORMAT_R8_UNORM
530 { D3DFMT_L16, 16, 16, 0, 0, 0 }, // DXGI_FORMAT_R16_UNORM
533 static const uint s_d3dFormatCount = sizeof(s_d3dFormats) / sizeof(s_d3dFormats[0]);
537 static uint findD3D9Format(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
539 for (int i = 0; i < s_d3dFormatCount; i++)
541 if (s_d3dFormats[i].bitcount == bitcount &&
542 s_d3dFormats[i].rmask == rmask &&
543 s_d3dFormats[i].gmask == gmask &&
544 s_d3dFormats[i].bmask == bmask &&
545 s_d3dFormats[i].amask == amask)
547 return s_d3dFormats[i].format;
556 DDSHeader::DDSHeader()
558 this->fourcc = FOURCC_DDS;
560 this->flags = (DDSD_CAPS|DDSD_PIXELFORMAT);
565 this->mipmapcount = 0;
566 for (uint i = 0; i < 11; i++) this->reserved[i] = 0;
568 // Store version information on the reserved header attributes.
569 this->reserved[9] = FOURCC_NVTT;
570 this->reserved[10] = (2 << 16) | (1 << 8) | (0); // major.minor.revision
575 this->pf.bitcount = 0;
580 this->caps.caps1 = DDSCAPS_TEXTURE;
581 this->caps.caps2 = 0;
582 this->caps.caps3 = 0;
583 this->caps.caps4 = 0;
586 this->header10.dxgiFormat = DXGI_FORMAT_UNKNOWN;
587 this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_UNKNOWN;
588 this->header10.miscFlag = 0;
589 this->header10.arraySize = 0;
590 this->header10.reserved = 0;
593 void DDSHeader::setWidth(uint w)
595 this->flags |= DDSD_WIDTH;
599 void DDSHeader::setHeight(uint h)
601 this->flags |= DDSD_HEIGHT;
605 void DDSHeader::setDepth(uint d)
607 this->flags |= DDSD_DEPTH;
611 void DDSHeader::setMipmapCount(uint count)
613 if (count == 0 || count == 1)
615 this->flags &= ~DDSD_MIPMAPCOUNT;
616 this->mipmapcount = 1;
618 if (this->caps.caps2 == 0) {
619 this->caps.caps1 = DDSCAPS_TEXTURE;
622 this->caps.caps1 = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
627 this->flags |= DDSD_MIPMAPCOUNT;
628 this->mipmapcount = count;
630 this->caps.caps1 |= DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
634 void DDSHeader::setTexture2D()
636 this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
637 this->header10.arraySize = 1;
640 void DDSHeader::setTexture3D()
642 this->caps.caps2 = DDSCAPS2_VOLUME;
644 this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D;
645 this->header10.arraySize = 1;
648 void DDSHeader::setTextureCube()
650 this->caps.caps1 |= DDSCAPS_COMPLEX;
651 this->caps.caps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALL_FACES;
653 this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
654 this->header10.arraySize = 6;
657 void DDSHeader::setLinearSize(uint size)
659 this->flags &= ~DDSD_PITCH;
660 this->flags |= DDSD_LINEARSIZE;
664 void DDSHeader::setPitch(uint pitch)
666 this->flags &= ~DDSD_LINEARSIZE;
667 this->flags |= DDSD_PITCH;
671 void DDSHeader::setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3)
673 // set fourcc pixel format.
674 this->pf.flags = DDPF_FOURCC;
675 this->pf.fourcc = MAKEFOURCC(c0, c1, c2, c3);
677 this->pf.bitcount = 0;
684 void DDSHeader::setFormatCode(uint32 code)
686 // set fourcc pixel format.
687 this->pf.flags = DDPF_FOURCC;
688 this->pf.fourcc = code;
690 this->pf.bitcount = 0;
697 void DDSHeader::setSwizzleCode(uint8 c0, uint8 c1, uint8 c2, uint8 c3)
699 this->pf.bitcount = MAKEFOURCC(c0, c1, c2, c3);
703 void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
705 // Make sure the masks are correct.
706 if ((rmask & gmask) ||
712 printf("DDS: bad RGBA masks, pixel format not set\n");
716 if (rmask != 0 || gmask != 0 || bmask != 0)
718 if (gmask == 0 && bmask == 0)
720 this->pf.flags = DDPF_LUMINANCE;
724 this->pf.flags = DDPF_RGB;
728 this->pf.flags |= DDPF_ALPHAPIXELS;
733 this->pf.flags |= DDPF_ALPHA;
738 // Compute bit count from the masks.
739 uint total = rmask | gmask | bmask | amask;
746 // D3DX functions do not like this:
747 this->pf.fourcc = 0; //findD3D9Format(bitcount, rmask, gmask, bmask, amask);
748 /*if (this->pf.fourcc) {
749 this->pf.flags |= DDPF_FOURCC;
752 if (!(bitcount > 0 && bitcount <= 32)) {
753 printf("DDS: bad bit count, pixel format not set\n");
756 this->pf.bitcount = bitcount;
757 this->pf.rmask = rmask;
758 this->pf.gmask = gmask;
759 this->pf.bmask = bmask;
760 this->pf.amask = amask;
763 void DDSHeader::setDX10Format(uint format)
765 //this->pf.flags = 0;
766 this->pf.fourcc = FOURCC_DX10;
767 this->header10.dxgiFormat = format;
770 void DDSHeader::setNormalFlag(bool b)
772 if (b) this->pf.flags |= DDPF_NORMAL;
773 else this->pf.flags &= ~DDPF_NORMAL;
776 void DDSHeader::setSrgbFlag(bool b)
778 if (b) this->pf.flags |= DDPF_SRGB;
779 else this->pf.flags &= ~DDPF_SRGB;
782 void DDSHeader::setHasAlphaFlag(bool b)
784 if (b) this->pf.flags |= DDPF_ALPHAPIXELS;
785 else this->pf.flags &= ~DDPF_ALPHAPIXELS;
788 void DDSHeader::setUserVersion(int version)
790 this->reserved[7] = FOURCC_UVER;
791 this->reserved[8] = version;
795 void DDSHeader::swapBytes()
797 this->fourcc = POSH_LittleU32(this->fourcc);
798 this->size = POSH_LittleU32(this->size);
799 this->flags = POSH_LittleU32(this->flags);
800 this->height = POSH_LittleU32(this->height);
801 this->width = POSH_LittleU32(this->width);
802 this->pitch = POSH_LittleU32(this->pitch);
803 this->depth = POSH_LittleU32(this->depth);
804 this->mipmapcount = POSH_LittleU32(this->mipmapcount);
806 for (int i = 0; i < 11; i++) {
807 this->reserved[i] = POSH_LittleU32(this->reserved[i]);
810 this->pf.size = POSH_LittleU32(this->pf.size);
811 this->pf.flags = POSH_LittleU32(this->pf.flags);
812 this->pf.fourcc = POSH_LittleU32(this->pf.fourcc);
813 this->pf.bitcount = POSH_LittleU32(this->pf.bitcount);
814 this->pf.rmask = POSH_LittleU32(this->pf.rmask);
815 this->pf.gmask = POSH_LittleU32(this->pf.gmask);
816 this->pf.bmask = POSH_LittleU32(this->pf.bmask);
817 this->pf.amask = POSH_LittleU32(this->pf.amask);
818 this->caps.caps1 = POSH_LittleU32(this->caps.caps1);
819 this->caps.caps2 = POSH_LittleU32(this->caps.caps2);
820 this->caps.caps3 = POSH_LittleU32(this->caps.caps3);
821 this->caps.caps4 = POSH_LittleU32(this->caps.caps4);
822 this->notused = POSH_LittleU32(this->notused);
824 this->header10.dxgiFormat = POSH_LittleU32(this->header10.dxgiFormat);
825 this->header10.resourceDimension = POSH_LittleU32(this->header10.resourceDimension);
826 this->header10.miscFlag = POSH_LittleU32(this->header10.miscFlag);
827 this->header10.arraySize = POSH_LittleU32(this->header10.arraySize);
828 this->header10.reserved = POSH_LittleU32(this->header10.reserved);
832 bool DDSHeader::hasDX10Header() const
834 return this->pf.fourcc == FOURCC_DX10;
837 uint DDSHeader::signature() const
839 return this->reserved[9];
842 uint DDSHeader::toolVersion() const
844 return this->reserved[10];
847 uint DDSHeader::userVersion() const
849 if (this->reserved[7] == FOURCC_UVER) {
850 return this->reserved[8];
855 bool DDSHeader::isNormalMap() const
857 return (pf.flags & DDPF_NORMAL) != 0;
860 bool DDSHeader::isSrgb() const
862 return (pf.flags & DDPF_SRGB) != 0;
865 bool DDSHeader::hasAlpha() const
867 return (pf.flags & DDPF_ALPHAPIXELS) != 0;
870 uint DDSHeader::d3d9Format() const
872 if (pf.flags & DDPF_FOURCC) {
876 return findD3D9Format(pf.bitcount, pf.rmask, pf.gmask, pf.bmask, pf.amask);
880 DirectDrawSurface::DirectDrawSurface(unsigned char *mem, uint size) : stream(mem, size), header()
882 mem_read(stream, header);
884 // some ATI2 compressed normal maps do not have their
885 // normal flag set, so force it here (the original nvtt don't do
886 // this, but the decompressor has a -forcenormal flag)
887 if (header.pf.fourcc == FOURCC_ATI2) header.setNormalFlag(true);
890 DirectDrawSurface::~DirectDrawSurface()
894 bool DirectDrawSurface::isValid() const
896 if (header.fourcc != FOURCC_DDS || header.size != 124)
901 const uint required = (DDSD_WIDTH|DDSD_HEIGHT/*|DDSD_CAPS|DDSD_PIXELFORMAT*/);
902 if ( (header.flags & required) != required ) {
906 if (header.pf.size != 32) {
910 /* in some files DDSCAPS_TEXTURE is missing: silently ignore */
912 if ( !(header.caps.caps1 & DDSCAPS_TEXTURE) ) {
920 bool DirectDrawSurface::isSupported() const
922 if (header.hasDX10Header())
924 if (header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM ||
925 header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM ||
926 header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM ||
927 header.header10.dxgiFormat == DXGI_FORMAT_BC4_UNORM ||
928 header.header10.dxgiFormat == DXGI_FORMAT_BC5_UNORM)
937 if (header.pf.flags & DDPF_FOURCC)
939 if (header.pf.fourcc != FOURCC_DXT1 &&
940 header.pf.fourcc != FOURCC_DXT2 &&
941 header.pf.fourcc != FOURCC_DXT3 &&
942 header.pf.fourcc != FOURCC_DXT4 &&
943 header.pf.fourcc != FOURCC_DXT5 &&
944 header.pf.fourcc != FOURCC_RXGB &&
945 header.pf.fourcc != FOURCC_ATI1 &&
946 header.pf.fourcc != FOURCC_ATI2)
948 // Unknown fourcc code.
952 else if ((header.pf.flags & DDPF_RGB) || (header.pf.flags & DDPF_LUMINANCE))
954 // All RGB and luminance formats are supported now.
961 if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES)
963 // Cubemaps must contain all faces.
969 // @@ 3D textures not supported yet.
977 bool DirectDrawSurface::hasAlpha() const
979 if (header.hasDX10Header())
981 /* TODO: Update hasAlpha to handle all DX10 formats. */
983 header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM ||
984 header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM ||
985 header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM;
989 if (header.pf.flags & DDPF_RGB)
991 return header.pf.amask != 0;
993 else if (header.pf.flags & DDPF_FOURCC)
995 if (header.pf.fourcc == FOURCC_RXGB ||
996 header.pf.fourcc == FOURCC_ATI1 ||
997 header.pf.fourcc == FOURCC_ATI2 ||
998 header.pf.flags & DDPF_NORMAL)
1004 // @@ Here we could check the ALPHA_PIXELS flag, but nobody sets it. (except us?)
1013 uint DirectDrawSurface::mipmapCount() const
1015 if (header.flags & DDSD_MIPMAPCOUNT) return header.mipmapcount;
1019 uint DirectDrawSurface::fourCC() const
1021 return header.pf.fourcc;
1024 uint DirectDrawSurface::width() const
1026 if (header.flags & DDSD_WIDTH) return header.width;
1030 uint DirectDrawSurface::height() const
1032 if (header.flags & DDSD_HEIGHT) return header.height;
1036 uint DirectDrawSurface::depth() const
1038 if (header.flags & DDSD_DEPTH) return header.depth;
1042 bool DirectDrawSurface::isTexture1D() const
1044 if (header.hasDX10Header())
1046 return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE1D;
1051 bool DirectDrawSurface::isTexture2D() const
1053 if (header.hasDX10Header())
1055 return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE2D;
1059 return !isTexture3D() && !isTextureCube();
1063 bool DirectDrawSurface::isTexture3D() const
1065 if (header.hasDX10Header())
1067 return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE3D;
1071 return (header.caps.caps2 & DDSCAPS2_VOLUME) != 0;
1075 bool DirectDrawSurface::isTextureCube() const
1077 return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0;
1080 void DirectDrawSurface::setNormalFlag(bool b)
1082 header.setNormalFlag(b);
1085 void DirectDrawSurface::setHasAlphaFlag(bool b)
1087 header.setHasAlphaFlag(b);
1090 void DirectDrawSurface::setUserVersion(int version)
1092 header.setUserVersion(version);
1095 void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap)
1097 stream.seek(offset(face, mipmap));
1102 // Compute width and height.
1103 for (uint m = 0; m < mipmap; m++)
1109 img->allocate(w, h);
1113 img->setFormat(Image::Format_ARGB);
1117 img->setFormat(Image::Format_RGB);
1120 if (header.hasDX10Header())
1122 // So far only block formats supported.
1123 readBlockImage(img);
1127 if (header.pf.flags & DDPF_RGB)
1129 readLinearImage(img);
1131 else if (header.pf.flags & DDPF_FOURCC)
1133 readBlockImage(img);
1138 // It was easier to copy this function from upstream than to resync.
1139 // This should be removed if a resync ever occurs.
1140 void* DirectDrawSurface::readData(uint &rsize)
1142 uint header_size = 128; // sizeof(DDSHeader);
1143 if (header.hasDX10Header())
1145 header_size += 20; // sizeof(DDSHeader10);
1148 uint size = stream.size - header_size;
1151 unsigned char *data = new unsigned char[size];
1153 stream.seek(header_size);
1154 mem_read(stream, data, size);
1156 // Maybe check if size == rsize? assert() isn't in this scope...
1161 void DirectDrawSurface::readLinearImage(Image * img)
1164 const uint w = img->width();
1165 const uint h = img->height();
1168 PixelFormat::maskShiftAndSize(header.pf.rmask, &rshift, &rsize);
1171 PixelFormat::maskShiftAndSize(header.pf.gmask, &gshift, &gsize);
1174 PixelFormat::maskShiftAndSize(header.pf.bmask, &bshift, &bsize);
1177 PixelFormat::maskShiftAndSize(header.pf.amask, &ashift, &asize);
1179 uint byteCount = (header.pf.bitcount + 7) / 8;
1183 /* just in case... we could have segfaults later on if byteCount > 4 */
1184 printf("DDS: bitcount too large");
1188 // Read linear RGB images.
1189 for (uint y = 0; y < h; y++)
1191 for (uint x = 0; x < w; x++)
1194 mem_read(stream, (unsigned char *)(&c), byteCount);
1196 Color32 pixel(0, 0, 0, 0xFF);
1197 pixel.r = PixelFormat::convert((c & header.pf.rmask) >> rshift, rsize, 8);
1198 pixel.g = PixelFormat::convert((c & header.pf.gmask) >> gshift, gsize, 8);
1199 pixel.b = PixelFormat::convert((c & header.pf.bmask) >> bshift, bsize, 8);
1200 pixel.a = PixelFormat::convert((c & header.pf.amask) >> ashift, asize, 8);
1202 img->pixel(x, y) = pixel;
1207 void DirectDrawSurface::readBlockImage(Image * img)
1210 const uint w = img->width();
1211 const uint h = img->height();
1213 const uint bw = (w + 3) / 4;
1214 const uint bh = (h + 3) / 4;
1216 for (uint by = 0; by < bh; by++)
1218 for (uint bx = 0; bx < bw; bx++)
1222 // Read color block.
1225 // Write color block.
1226 for (uint y = 0; y < min(4U, h-4*by); y++)
1228 for (uint x = 0; x < min(4U, w-4*bx); x++)
1230 img->pixel(4*bx+x, 4*by+y) = block.color(x, y);
1237 static Color32 buildNormal(uint8 x, uint8 y)
1239 float nx = 2 * (x / 255.0f) - 1;
1240 float ny = 2 * (y / 255.0f) - 1;
1242 if (1 - nx*nx - ny*ny > 0) nz = sqrt(1 - nx*nx - ny*ny);
1243 uint8 z = clamp(int(255.0f * (nz + 1) / 2.0f), 0, 255);
1245 return Color32(x, y, z);
1249 void DirectDrawSurface::readBlock(ColorBlock * rgba)
1251 uint fourcc = header.pf.fourcc;
1253 // Map DX10 block formats to fourcc codes.
1254 if (header.hasDX10Header())
1256 if (header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM) fourcc = FOURCC_DXT1;
1257 if (header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM) fourcc = FOURCC_DXT3;
1258 if (header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM) fourcc = FOURCC_DXT5;
1259 if (header.header10.dxgiFormat == DXGI_FORMAT_BC4_UNORM) fourcc = FOURCC_ATI1;
1260 if (header.header10.dxgiFormat == DXGI_FORMAT_BC5_UNORM) fourcc = FOURCC_ATI2;
1264 if (fourcc == FOURCC_DXT1)
1267 mem_read(stream, block);
1268 block.decodeBlock(rgba);
1270 else if (fourcc == FOURCC_DXT2 ||
1271 header.pf.fourcc == FOURCC_DXT3)
1274 mem_read(stream, block);
1275 block.decodeBlock(rgba);
1277 else if (fourcc == FOURCC_DXT4 ||
1278 header.pf.fourcc == FOURCC_DXT5 ||
1279 header.pf.fourcc == FOURCC_RXGB)
1282 mem_read(stream, block);
1283 block.decodeBlock(rgba);
1285 if (fourcc == FOURCC_RXGB)
1288 for (int i = 0; i < 16; i++)
1290 Color32 & c = rgba->color(i);
1297 else if (fourcc == FOURCC_ATI1)
1300 mem_read(stream, block);
1301 block.decodeBlock(rgba);
1303 else if (fourcc == FOURCC_ATI2)
1306 mem_read(stream, block);
1307 block.decodeBlock(rgba);
1310 // If normal flag set, convert to normal.
1311 if (header.pf.flags & DDPF_NORMAL)
1313 if (fourcc == FOURCC_ATI2)
1315 for (int i = 0; i < 16; i++)
1317 Color32 & c = rgba->color(i);
1318 c = buildNormal(c.r, c.g);
1321 else if (fourcc == FOURCC_DXT5)
1323 for (int i = 0; i < 16; i++)
1325 Color32 & c = rgba->color(i);
1326 c = buildNormal(c.a, c.g);
1333 uint DirectDrawSurface::blockSize() const
1335 switch (header.pf.fourcc)
1348 switch (header.header10.dxgiFormat)
1350 case DXGI_FORMAT_BC1_TYPELESS:
1351 case DXGI_FORMAT_BC1_UNORM:
1352 case DXGI_FORMAT_BC1_UNORM_SRGB:
1353 case DXGI_FORMAT_BC4_TYPELESS:
1354 case DXGI_FORMAT_BC4_UNORM:
1355 case DXGI_FORMAT_BC4_SNORM:
1357 case DXGI_FORMAT_BC2_TYPELESS:
1358 case DXGI_FORMAT_BC2_UNORM:
1359 case DXGI_FORMAT_BC2_UNORM_SRGB:
1360 case DXGI_FORMAT_BC3_TYPELESS:
1361 case DXGI_FORMAT_BC3_UNORM:
1362 case DXGI_FORMAT_BC3_UNORM_SRGB:
1363 case DXGI_FORMAT_BC5_TYPELESS:
1364 case DXGI_FORMAT_BC5_UNORM:
1365 case DXGI_FORMAT_BC5_SNORM:
1370 // Not a block image.
1374 uint DirectDrawSurface::mipmapSize(uint mipmap) const
1380 for (uint m = 0; m < mipmap; m++)
1387 if (header.pf.flags & DDPF_FOURCC)
1389 // @@ How are 3D textures aligned?
1392 return blockSize() * w * h;
1394 else if (header.pf.flags & DDPF_RGB || (header.pf.flags & DDPF_LUMINANCE))
1396 uint pitch = computePitch(w, header.pf.bitcount, 8); // Asuming 8 bit alignment, which is the same D3DX expects.
1398 return pitch * h * d;
1401 printf("DDS: mipmap format not supported\n");
1406 uint DirectDrawSurface::faceSize() const
1408 const uint count = mipmapCount();
1411 for (uint m = 0; m < count; m++)
1413 size += mipmapSize(m);
1419 uint DirectDrawSurface::offset(const uint face, const uint mipmap)
1421 uint size = 128; // sizeof(DDSHeader);
1423 if (header.hasDX10Header())
1425 size += 20; // sizeof(DDSHeader10);
1430 size += face * faceSize();
1433 for (uint m = 0; m < mipmap; m++)
1435 size += mipmapSize(m);
1442 void DirectDrawSurface::printInfo() const
1444 printf("Flags: 0x%.8X\n", header.flags);
1445 if (header.flags & DDSD_CAPS) printf("\tDDSD_CAPS\n");
1446 if (header.flags & DDSD_PIXELFORMAT) printf("\tDDSD_PIXELFORMAT\n");
1447 if (header.flags & DDSD_WIDTH) printf("\tDDSD_WIDTH\n");
1448 if (header.flags & DDSD_HEIGHT) printf("\tDDSD_HEIGHT\n");
1449 if (header.flags & DDSD_DEPTH) printf("\tDDSD_DEPTH\n");
1450 if (header.flags & DDSD_PITCH) printf("\tDDSD_PITCH\n");
1451 if (header.flags & DDSD_LINEARSIZE) printf("\tDDSD_LINEARSIZE\n");
1452 if (header.flags & DDSD_MIPMAPCOUNT) printf("\tDDSD_MIPMAPCOUNT\n");
1454 printf("Height: %u\n", header.height);
1455 printf("Width: %u\n", header.width);
1456 printf("Depth: %u\n", header.depth);
1457 if (header.flags & DDSD_PITCH) printf("Pitch: %u\n", header.pitch);
1458 else if (header.flags & DDSD_LINEARSIZE) printf("Linear size: %u\n", header.pitch);
1459 printf("Mipmap count: %u\n", header.mipmapcount);
1461 printf("Pixel Format:\n");
1462 printf("\tFlags: 0x%.8X\n", header.pf.flags);
1463 if (header.pf.flags & DDPF_RGB) printf("\t\tDDPF_RGB\n");
1464 if (header.pf.flags & DDPF_LUMINANCE) printf("\t\tDDPF_LUMINANCE\n");
1465 if (header.pf.flags & DDPF_FOURCC) printf("\t\tDDPF_FOURCC\n");
1466 if (header.pf.flags & DDPF_ALPHAPIXELS) printf("\t\tDDPF_ALPHAPIXELS\n");
1467 if (header.pf.flags & DDPF_ALPHA) printf("\t\tDDPF_ALPHA\n");
1468 if (header.pf.flags & DDPF_PALETTEINDEXED1) printf("\t\tDDPF_PALETTEINDEXED1\n");
1469 if (header.pf.flags & DDPF_PALETTEINDEXED2) printf("\t\tDDPF_PALETTEINDEXED2\n");
1470 if (header.pf.flags & DDPF_PALETTEINDEXED4) printf("\t\tDDPF_PALETTEINDEXED4\n");
1471 if (header.pf.flags & DDPF_PALETTEINDEXED8) printf("\t\tDDPF_PALETTEINDEXED8\n");
1472 if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n");
1473 if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n");
1475 if (header.pf.fourcc != 0) {
1476 // Display fourcc code even when DDPF_FOURCC flag not set.
1477 printf("\tFourCC: '%c%c%c%c' (0x%.8X)\n",
1478 ((header.pf.fourcc >> 0) & 0xFF),
1479 ((header.pf.fourcc >> 8) & 0xFF),
1480 ((header.pf.fourcc >> 16) & 0xFF),
1481 ((header.pf.fourcc >> 24) & 0xFF),
1485 if ((header.pf.flags & DDPF_FOURCC) && (header.pf.bitcount != 0))
1487 printf("\tSwizzle: '%c%c%c%c' (0x%.8X)\n",
1488 (header.pf.bitcount >> 0) & 0xFF,
1489 (header.pf.bitcount >> 8) & 0xFF,
1490 (header.pf.bitcount >> 16) & 0xFF,
1491 (header.pf.bitcount >> 24) & 0xFF,
1492 header.pf.bitcount);
1496 printf("\tBit count: %u\n", header.pf.bitcount);
1499 printf("\tRed mask: 0x%.8X\n", header.pf.rmask);
1500 printf("\tGreen mask: 0x%.8X\n", header.pf.gmask);
1501 printf("\tBlue mask: 0x%.8X\n", header.pf.bmask);
1502 printf("\tAlpha mask: 0x%.8X\n", header.pf.amask);
1505 printf("\tCaps 1: 0x%.8X\n", header.caps.caps1);
1506 if (header.caps.caps1 & DDSCAPS_COMPLEX) printf("\t\tDDSCAPS_COMPLEX\n");
1507 if (header.caps.caps1 & DDSCAPS_TEXTURE) printf("\t\tDDSCAPS_TEXTURE\n");
1508 if (header.caps.caps1 & DDSCAPS_MIPMAP) printf("\t\tDDSCAPS_MIPMAP\n");
1510 printf("\tCaps 2: 0x%.8X\n", header.caps.caps2);
1511 if (header.caps.caps2 & DDSCAPS2_VOLUME) printf("\t\tDDSCAPS2_VOLUME\n");
1512 else if (header.caps.caps2 & DDSCAPS2_CUBEMAP)
1514 printf("\t\tDDSCAPS2_CUBEMAP\n");
1515 if ((header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) == DDSCAPS2_CUBEMAP_ALL_FACES) printf("\t\tDDSCAPS2_CUBEMAP_ALL_FACES\n");
1517 if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEX\n");
1518 if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEX\n");
1519 if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEY\n");
1520 if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEY\n");
1521 if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEZ\n");
1522 if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEZ\n");
1526 printf("\tCaps 3: 0x%.8X\n", header.caps.caps3);
1527 printf("\tCaps 4: 0x%.8X\n", header.caps.caps4);
1529 if (header.hasDX10Header())
1531 printf("DX10 Header:\n");
1532 printf("\tDXGI Format: %u (%s)\n", header.header10.dxgiFormat, getDxgiFormatString((DXGI_FORMAT)header.header10.dxgiFormat));
1533 printf("\tResource dimension: %u (%s)\n", header.header10.resourceDimension, getD3d10ResourceDimensionString((D3D10_RESOURCE_DIMENSION)header.header10.resourceDimension));
1534 printf("\tMisc flag: %u\n", header.header10.miscFlag);
1535 printf("\tArray size: %u\n", header.header10.arraySize);
1538 if (header.reserved[9] == FOURCC_NVTT)
1540 int major = (header.reserved[10] >> 16) & 0xFF;
1541 int minor = (header.reserved[10] >> 8) & 0xFF;
1542 int revision= header.reserved[10] & 0xFF;
1544 printf("Version:\n");
1545 printf("\tNVIDIA Texture Tools %d.%d.%d\n", major, minor, revision);
1548 if (header.reserved[7] == FOURCC_UVER)
1550 printf("User Version: %u\n", header.reserved[8]);