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