remove redundant trailing slashes
[blender.git] / source / blender / imbuf / intern / dds / DirectDrawSurface.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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.
8  *
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.
13  *
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.
17  *
18  * Contributors: Amorilia (amorilia@users.sourceforge.net)
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/imbuf/intern/dds/DirectDrawSurface.cpp
24  *  \ingroup imbdds
25  */
26
27
28 /*
29  * This file is based on a similar file from the NVIDIA texture tools
30  * (http://nvidia-texture-tools.googlecode.com/)
31  *
32  * Original license from NVIDIA follows.
33  */
34
35 // Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
36 // 
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
44 // conditions:
45 // 
46 // The above copyright notice and this permission notice shall be
47 // included in all copies or substantial portions of the Software.
48 // 
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.
57
58 #include <DirectDrawSurface.h>
59 #include <BlockDXT.h>
60 #include <PixelFormat.h>
61
62 #include <stdio.h> // printf
63 #include <math.h>  // sqrt
64 #include <sys/types.h>
65
66 /*** declarations ***/
67
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 ))
72 #endif
73
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');
84
85 static const uint FOURCC_A2XY = MAKEFOURCC('A', '2', 'X', 'Y');
86         
87 static const uint FOURCC_DX10 = MAKEFOURCC('D', 'X', '1', '0');
88
89 static const uint FOURCC_UVER = MAKEFOURCC('U', 'V', 'E', 'R');
90
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;
108
109 static const uint D3DFMT_A16B16G16R16 = 36;
110
111 // Palette formats.
112 static const uint D3DFMT_A8P8 = 40;
113 static const uint D3DFMT_P8 = 41;
114         
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;
120
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;
128         
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;
137         
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;
143
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;
151
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;
162
163 // Custom NVTT flags.
164 static const uint DDPF_NORMAL = 0x80000000U;  
165 static const uint DDPF_SRGB = 0x40000000U;
166
167         // DX10 formats.
168         enum DXGI_FORMAT
169         {
170                 DXGI_FORMAT_UNKNOWN = 0,
171                 
172                 DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
173                 DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
174                 DXGI_FORMAT_R32G32B32A32_UINT = 3,
175                 DXGI_FORMAT_R32G32B32A32_SINT = 4,
176                 
177                 DXGI_FORMAT_R32G32B32_TYPELESS = 5,
178                 DXGI_FORMAT_R32G32B32_FLOAT = 6,
179                 DXGI_FORMAT_R32G32B32_UINT = 7,
180                 DXGI_FORMAT_R32G32B32_SINT = 8,
181                 
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,
188                 
189                 DXGI_FORMAT_R32G32_TYPELESS = 15,
190                 DXGI_FORMAT_R32G32_FLOAT = 16,
191                 DXGI_FORMAT_R32G32_UINT = 17,
192                 DXGI_FORMAT_R32G32_SINT = 18,
193                 
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,
198                 
199                 DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
200                 DXGI_FORMAT_R10G10B10A2_UNORM = 24,
201                 DXGI_FORMAT_R10G10B10A2_UINT = 25,
202                 
203                 DXGI_FORMAT_R11G11B10_FLOAT = 26,
204                 
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,
211                 
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,
218                 
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,
224                 
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,
229                 
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,
235                 
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,
243                 
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,
250                 
251                 DXGI_FORMAT_R1_UNORM = 66,
252                 
253                 DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
254                 
255                 DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
256                 DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
257                 
258                 DXGI_FORMAT_BC1_TYPELESS = 70,
259                 DXGI_FORMAT_BC1_UNORM = 71,
260                 DXGI_FORMAT_BC1_UNORM_SRGB = 72,
261                 
262                 DXGI_FORMAT_BC2_TYPELESS = 73,
263                 DXGI_FORMAT_BC2_UNORM = 74,
264                 DXGI_FORMAT_BC2_UNORM_SRGB = 75,
265                 
266                 DXGI_FORMAT_BC3_TYPELESS = 76,
267                 DXGI_FORMAT_BC3_UNORM = 77,
268                 DXGI_FORMAT_BC3_UNORM_SRGB = 78,
269                 
270                 DXGI_FORMAT_BC4_TYPELESS = 79,
271                 DXGI_FORMAT_BC4_UNORM = 80,
272                 DXGI_FORMAT_BC4_SNORM = 81,
273                 
274                 DXGI_FORMAT_BC5_TYPELESS = 82,
275                 DXGI_FORMAT_BC5_UNORM = 83,
276                 DXGI_FORMAT_BC5_SNORM = 84,
277                 
278                 DXGI_FORMAT_B5G6R5_UNORM = 85,
279                 DXGI_FORMAT_B5G5R5A1_UNORM = 86,
280                 DXGI_FORMAT_B8G8R8A8_UNORM = 87,
281                 DXGI_FORMAT_B8G8R8X8_UNORM = 88,
282
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,
288
289         DXGI_FORMAT_BC6H_TYPELESS = 94,
290         DXGI_FORMAT_BC6H_UF16 = 95,
291         DXGI_FORMAT_BC6H_SF16 = 96,
292
293         DXGI_FORMAT_BC7_TYPELESS = 97,
294         DXGI_FORMAT_BC7_UNORM = 98,
295         DXGI_FORMAT_BC7_UNORM_SRGB = 99,
296         };
297
298         enum D3D10_RESOURCE_DIMENSION
299         {
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,
305         };
306
307
308         const char * getDxgiFormatString(DXGI_FORMAT dxgiFormat)
309         {
310 #define CASE(format) case DXGI_FORMAT_##format: return #format
311                 switch(dxgiFormat)
312                 {
313                         CASE(UNKNOWN);
314                         
315                         CASE(R32G32B32A32_TYPELESS);
316                         CASE(R32G32B32A32_FLOAT);
317                         CASE(R32G32B32A32_UINT);
318                         CASE(R32G32B32A32_SINT);
319                         
320                         CASE(R32G32B32_TYPELESS);
321                         CASE(R32G32B32_FLOAT);
322                         CASE(R32G32B32_UINT);
323                         CASE(R32G32B32_SINT);
324                         
325                         CASE(R16G16B16A16_TYPELESS);
326                         CASE(R16G16B16A16_FLOAT);
327                         CASE(R16G16B16A16_UNORM);
328                         CASE(R16G16B16A16_UINT);
329                         CASE(R16G16B16A16_SNORM);
330                         CASE(R16G16B16A16_SINT);
331                         
332                         CASE(R32G32_TYPELESS);
333                         CASE(R32G32_FLOAT);
334                         CASE(R32G32_UINT);
335                         CASE(R32G32_SINT);
336                         
337                         CASE(R32G8X24_TYPELESS);
338                         CASE(D32_FLOAT_S8X24_UINT);
339                         CASE(R32_FLOAT_X8X24_TYPELESS);
340                         CASE(X32_TYPELESS_G8X24_UINT);
341                         
342                         CASE(R10G10B10A2_TYPELESS);
343                         CASE(R10G10B10A2_UNORM);
344                         CASE(R10G10B10A2_UINT);
345                         
346                         CASE(R11G11B10_FLOAT);
347                         
348                         CASE(R8G8B8A8_TYPELESS);
349                         CASE(R8G8B8A8_UNORM);
350                         CASE(R8G8B8A8_UNORM_SRGB);
351                         CASE(R8G8B8A8_UINT);
352                         CASE(R8G8B8A8_SNORM);
353                         CASE(R8G8B8A8_SINT);
354                         
355                         CASE(R16G16_TYPELESS);
356                         CASE(R16G16_FLOAT);
357                         CASE(R16G16_UNORM);
358                         CASE(R16G16_UINT);
359                         CASE(R16G16_SNORM);
360                         CASE(R16G16_SINT);
361                         
362                         CASE(R32_TYPELESS);
363                         CASE(D32_FLOAT);
364                         CASE(R32_FLOAT);
365                         CASE(R32_UINT);
366                         CASE(R32_SINT);
367                         
368                         CASE(R24G8_TYPELESS);
369                         CASE(D24_UNORM_S8_UINT);
370                         CASE(R24_UNORM_X8_TYPELESS);
371                         CASE(X24_TYPELESS_G8_UINT);
372                         
373                         CASE(R8G8_TYPELESS);
374                         CASE(R8G8_UNORM);
375                         CASE(R8G8_UINT);
376                         CASE(R8G8_SNORM);
377                         CASE(R8G8_SINT);
378                         
379                         CASE(R16_TYPELESS);
380                         CASE(R16_FLOAT);
381                         CASE(D16_UNORM);
382                         CASE(R16_UNORM);
383                         CASE(R16_UINT);
384                         CASE(R16_SNORM);
385                         CASE(R16_SINT);
386                         
387                         CASE(R8_TYPELESS);
388                         CASE(R8_UNORM);
389                         CASE(R8_UINT);
390                         CASE(R8_SNORM);
391                         CASE(R8_SINT);
392                         CASE(A8_UNORM);
393
394                         CASE(R1_UNORM);
395                 
396                         CASE(R9G9B9E5_SHAREDEXP);
397                         
398                         CASE(R8G8_B8G8_UNORM);
399                         CASE(G8R8_G8B8_UNORM);
400
401                         CASE(BC1_TYPELESS);
402                         CASE(BC1_UNORM);
403                         CASE(BC1_UNORM_SRGB);
404                 
405                         CASE(BC2_TYPELESS);
406                         CASE(BC2_UNORM);
407                         CASE(BC2_UNORM_SRGB);
408                 
409                         CASE(BC3_TYPELESS);
410                         CASE(BC3_UNORM);
411                         CASE(BC3_UNORM_SRGB);
412                 
413                         CASE(BC4_TYPELESS);
414                         CASE(BC4_UNORM);
415                         CASE(BC4_SNORM);
416                 
417                         CASE(BC5_TYPELESS);
418                         CASE(BC5_UNORM);
419                         CASE(BC5_SNORM);
420
421                         CASE(B5G6R5_UNORM);
422                         CASE(B5G5R5A1_UNORM);
423                         CASE(B8G8R8A8_UNORM);
424                         CASE(B8G8R8X8_UNORM);
425
426                         default: 
427                                 return "UNKNOWN";
428                 }
429 #undef CASE
430         }
431         
432         const char * getD3d10ResourceDimensionString(D3D10_RESOURCE_DIMENSION resourceDimension)
433         {
434                 switch(resourceDimension)
435                 {
436                         default:
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";
442                 }
443         }
444
445 /*** implementation ***/
446
447 void mem_read(Stream & mem, DDSPixelFormat & pf)
448 {
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);
457 }
458
459 void mem_read(Stream & mem, DDSCaps & caps)
460 {
461         mem_read(mem, caps.caps1);
462         mem_read(mem, caps.caps2);
463         mem_read(mem, caps.caps3);
464         mem_read(mem, caps.caps4);
465 }
466
467 void mem_read(Stream & mem, DDSHeader10 & header)
468 {
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);
474 }
475
476 void mem_read(Stream & mem, DDSHeader & header)
477 {
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);
490
491         if (header.hasDX10Header())
492         {
493                 mem_read(mem, header.header10);
494         }
495 }
496
497 namespace
498 {
499     struct FormatDescriptor
500     {
501         uint format;
502         uint bitcount;
503         uint rmask;
504         uint gmask;
505         uint bmask;
506         uint amask;
507     };
508
509     static const FormatDescriptor s_d3dFormats[] =
510     {
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 },
528
529         { D3DFMT_L8,                    8,  8,          0,          0,          0 },           // DXGI_FORMAT_R8_UNORM 
530         { D3DFMT_L16,                   16, 16,         0,          0,          0 },           // DXGI_FORMAT_R16_UNORM
531     };
532
533     static const uint s_d3dFormatCount = sizeof(s_d3dFormats) / sizeof(s_d3dFormats[0]);
534
535 } // namespace
536
537 uint findD3D9Format(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
538 {
539     for (int i = 0; i < s_d3dFormatCount; i++)
540         {
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)
546             {
547                 return s_d3dFormats[i].format;
548             }
549         }
550
551         return 0;
552     }
553
554
555
556 DDSHeader::DDSHeader()
557 {
558         this->fourcc = FOURCC_DDS;
559         this->size = 124;
560         this->flags  = (DDSD_CAPS|DDSD_PIXELFORMAT);
561         this->height = 0;
562         this->width = 0;
563         this->pitch = 0;
564         this->depth = 0;
565         this->mipmapcount = 0;
566         for (uint i = 0; i < 11; i++) this->reserved[i] = 0;
567
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
571
572         this->pf.size = 32;
573         this->pf.flags = 0;
574         this->pf.fourcc = 0;
575         this->pf.bitcount = 0;
576         this->pf.rmask = 0;
577         this->pf.gmask = 0;
578         this->pf.bmask = 0;
579         this->pf.amask = 0;
580         this->caps.caps1 = DDSCAPS_TEXTURE;
581         this->caps.caps2 = 0;
582         this->caps.caps3 = 0;
583         this->caps.caps4 = 0;
584         this->notused = 0;
585
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;
591 }
592
593 void DDSHeader::setWidth(uint w)
594 {
595         this->flags |= DDSD_WIDTH;
596         this->width = w;
597 }
598
599 void DDSHeader::setHeight(uint h)
600 {
601         this->flags |= DDSD_HEIGHT;
602         this->height = h;
603 }
604
605 void DDSHeader::setDepth(uint d)
606 {
607         this->flags |= DDSD_DEPTH;
608         this->depth = d;
609 }
610
611 void DDSHeader::setMipmapCount(uint count)
612 {
613         if (count == 0 || count == 1)
614         {
615                 this->flags &= ~DDSD_MIPMAPCOUNT;
616         this->mipmapcount = 1;
617
618                 if (this->caps.caps2 == 0) {
619                         this->caps.caps1 = DDSCAPS_TEXTURE;
620                 }
621                 else {
622                         this->caps.caps1 = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
623                 }
624         }
625         else
626         {
627                 this->flags |= DDSD_MIPMAPCOUNT;
628                 this->mipmapcount = count;
629
630                 this->caps.caps1 |= DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
631         }
632 }
633
634 void DDSHeader::setTexture2D()
635 {
636         this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
637         this->header10.arraySize = 1;
638 }
639
640 void DDSHeader::setTexture3D()
641 {
642         this->caps.caps2 = DDSCAPS2_VOLUME;
643
644         this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D;
645         this->header10.arraySize = 1;
646 }
647
648 void DDSHeader::setTextureCube()
649 {
650         this->caps.caps1 |= DDSCAPS_COMPLEX;
651         this->caps.caps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALL_FACES;
652
653         this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
654         this->header10.arraySize = 6;
655 }
656
657 void DDSHeader::setLinearSize(uint size)
658 {
659         this->flags &= ~DDSD_PITCH;
660         this->flags |= DDSD_LINEARSIZE;
661         this->pitch = size;
662 }
663
664 void DDSHeader::setPitch(uint pitch)
665 {
666         this->flags &= ~DDSD_LINEARSIZE;
667         this->flags |= DDSD_PITCH;
668         this->pitch = pitch;
669 }
670
671 void DDSHeader::setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3)
672 {
673         // set fourcc pixel format.
674         this->pf.flags = DDPF_FOURCC;
675         this->pf.fourcc = MAKEFOURCC(c0, c1, c2, c3);
676
677         this->pf.bitcount = 0;
678         this->pf.rmask = 0;
679         this->pf.gmask = 0;
680         this->pf.bmask = 0;
681         this->pf.amask = 0;
682 }
683
684 void DDSHeader::setFormatCode(uint32 code)
685 {
686         // set fourcc pixel format.
687         this->pf.flags = DDPF_FOURCC;
688         this->pf.fourcc = code;
689         
690         this->pf.bitcount = 0;
691         this->pf.rmask = 0;
692         this->pf.gmask = 0;
693         this->pf.bmask = 0;
694         this->pf.amask = 0;
695 }
696
697 void DDSHeader::setSwizzleCode(uint8 c0, uint8 c1, uint8 c2, uint8 c3)
698 {
699         this->pf.bitcount = MAKEFOURCC(c0, c1, c2, c3);
700 }
701
702
703 void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
704 {
705         // Make sure the masks are correct.
706         if ((rmask & gmask) ||
707                 (rmask & bmask) ||
708                 (rmask & amask) ||
709                 (gmask & bmask) ||
710                 (gmask & amask) ||
711                 (bmask & amask)) {
712                 printf("DDS: bad RGBA masks, pixel format not set\n");
713                 return;
714         }
715
716         if (rmask != 0 || gmask != 0 || bmask != 0)
717         {
718         if (gmask == 0 && bmask == 0)
719         {
720             this->pf.flags = DDPF_LUMINANCE;
721         }
722         else
723         {
724                     this->pf.flags = DDPF_RGB;
725         }
726
727                 if (amask != 0) {
728                         this->pf.flags |= DDPF_ALPHAPIXELS;
729                 }
730         }
731         else if (amask != 0)
732         {
733                 this->pf.flags |= DDPF_ALPHA;
734         }
735
736         if (bitcount == 0)
737         {
738                 // Compute bit count from the masks.
739                 uint total = rmask | gmask | bmask | amask;
740                 while(total != 0) {
741                         bitcount++;
742                         total >>= 1;
743                 }
744         }
745
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;
750     }*/
751
752         if (!(bitcount > 0 && bitcount <= 32)) {
753                 printf("DDS: bad bit count, pixel format not set\n");
754                 return;
755         }
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;
761 }
762
763 void DDSHeader::setDX10Format(uint format)
764 {
765         //this->pf.flags = 0;
766         this->pf.fourcc = FOURCC_DX10;
767         this->header10.dxgiFormat = format;
768 }
769
770 void DDSHeader::setNormalFlag(bool b)
771 {
772         if (b) this->pf.flags |= DDPF_NORMAL;
773         else this->pf.flags &= ~DDPF_NORMAL;
774 }
775
776 void DDSHeader::setSrgbFlag(bool b)
777 {
778     if (b) this->pf.flags |= DDPF_SRGB;
779     else this->pf.flags &= ~DDPF_SRGB;
780 }
781
782 void DDSHeader::setHasAlphaFlag(bool b)
783 {
784         if (b) this->pf.flags |= DDPF_ALPHAPIXELS;
785         else this->pf.flags &= ~DDPF_ALPHAPIXELS;
786 }
787
788 void DDSHeader::setUserVersion(int version)
789 {
790     this->reserved[7] = FOURCC_UVER;
791     this->reserved[8] = version;
792 }
793
794 /*
795 void DDSHeader::swapBytes()
796 {
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);
805         
806         for(int i = 0; i < 11; i++) {
807                 this->reserved[i] = POSH_LittleU32(this->reserved[i]);
808         }
809
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);
823
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);
829 }
830 */
831
832 bool DDSHeader::hasDX10Header() const
833 {
834         return this->pf.fourcc == FOURCC_DX10;
835 }
836
837 uint DDSHeader::signature() const
838 {
839     return this->reserved[9];
840 }
841
842 uint DDSHeader::toolVersion() const
843 {
844     return this->reserved[10];
845 }
846
847 uint DDSHeader::userVersion() const
848 {
849     if (this->reserved[7] == FOURCC_UVER) {
850         return this->reserved[8];
851     }
852     return 0;
853 }
854
855 bool DDSHeader::isNormalMap() const
856 {
857     return (pf.flags & DDPF_NORMAL) != 0;
858 }
859
860 bool DDSHeader::isSrgb() const
861 {
862     return (pf.flags & DDPF_SRGB) != 0;
863 }
864
865 bool DDSHeader::hasAlpha() const
866 {
867     return (pf.flags & DDPF_ALPHAPIXELS) != 0;
868 }
869
870 uint DDSHeader::d3d9Format() const
871 {
872     if (pf.flags & DDPF_FOURCC) {
873         return pf.fourcc;
874     }
875     else {
876         return findD3D9Format(pf.bitcount, pf.rmask, pf.gmask, pf.bmask, pf.amask);
877     }
878 }
879
880 DirectDrawSurface::DirectDrawSurface(unsigned char *mem, uint size) : stream(mem, size), header()
881 {
882         mem_read(stream, header);
883
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);
888 }
889
890 DirectDrawSurface::~DirectDrawSurface()
891 {
892 }
893
894 bool DirectDrawSurface::isValid() const
895 {
896         if (header.fourcc != FOURCC_DDS || header.size != 124)
897         {
898                 return false;
899         }
900         
901         const uint required = (DDSD_WIDTH|DDSD_HEIGHT/*|DDSD_CAPS|DDSD_PIXELFORMAT*/);
902         if( (header.flags & required) != required ) {
903                 return false;
904         }
905         
906         if (header.pf.size != 32) {
907                 return false;
908         }
909
910         /* in some files DDSCAPS_TEXTURE is missing: silently ignore */
911         /*
912         if( !(header.caps.caps1 & DDSCAPS_TEXTURE) ) {
913                 return false;
914         }
915         */
916
917         return true;
918 }
919
920 bool DirectDrawSurface::isSupported() const
921 {
922         if (header.hasDX10Header())
923         {
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)
929                 {
930                         return true;
931                 }
932
933                 return false;
934         }
935         else
936         {
937                 if (header.pf.flags & DDPF_FOURCC)
938                 {
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)
947                         {
948                                 // Unknown fourcc code.
949                                 return false;
950                         }
951                 }
952         else if ((header.pf.flags & DDPF_RGB) || (header.pf.flags & DDPF_LUMINANCE))
953         {
954             // All RGB and luminance formats are supported now.
955                 }
956                 else
957                 {
958                         return false;
959                 }
960                 
961                 if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES)
962                 {
963                         // Cubemaps must contain all faces.
964                         return false;
965                 }
966         
967                 if (isTexture3D())
968                 {
969                         // @@ 3D textures not supported yet.
970                         return false;
971                 }
972         }
973         
974         return true;
975 }
976
977 bool DirectDrawSurface::hasAlpha() const
978 {
979         if (header.hasDX10Header())
980         {
981                 /* TODO: Update hasAlpha to handle all DX10 formats. */
982                 return 
983                         header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM ||
984                         header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM ||
985                         header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM;
986         }
987         else
988         {
989                 if (header.pf.flags & DDPF_RGB) 
990                 {
991                         return header.pf.amask != 0;
992                 }
993                 else if (header.pf.flags & DDPF_FOURCC)
994                 {
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)
999                         {
1000                                 return false;
1001                         }
1002                         else
1003                         {
1004                 // @@ Here we could check the ALPHA_PIXELS flag, but nobody sets it. (except us?)
1005                                 return true;
1006                         }
1007                 }
1008
1009                 return false;
1010         }
1011 }
1012
1013 uint DirectDrawSurface::mipmapCount() const
1014 {
1015         if (header.flags & DDSD_MIPMAPCOUNT) return header.mipmapcount;
1016         else return 1;
1017 }
1018
1019
1020 uint DirectDrawSurface::width() const
1021 {
1022         if (header.flags & DDSD_WIDTH) return header.width;
1023         else return 1;
1024 }
1025
1026 uint DirectDrawSurface::height() const
1027 {
1028         if (header.flags & DDSD_HEIGHT) return header.height;
1029         else return 1;
1030 }
1031
1032 uint DirectDrawSurface::depth() const
1033 {
1034         if (header.flags & DDSD_DEPTH) return header.depth;
1035         else return 1;
1036 }
1037
1038 bool DirectDrawSurface::isTexture1D() const
1039 {
1040         if (header.hasDX10Header())
1041         {
1042                 return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE1D;
1043         }
1044         return false;
1045 }
1046
1047 bool DirectDrawSurface::isTexture2D() const
1048 {
1049         if (header.hasDX10Header())
1050         {
1051                 return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE2D;
1052         }
1053         else
1054         {
1055                 return !isTexture3D() && !isTextureCube();
1056         }
1057 }
1058
1059 bool DirectDrawSurface::isTexture3D() const
1060 {
1061         if (header.hasDX10Header())
1062         {
1063                 return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE3D;
1064         }
1065         else
1066         {
1067         return (header.caps.caps2 & DDSCAPS2_VOLUME) != 0;
1068         }
1069 }
1070
1071 bool DirectDrawSurface::isTextureCube() const
1072 {
1073         return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0;
1074 }
1075
1076 void DirectDrawSurface::setNormalFlag(bool b)
1077 {
1078         header.setNormalFlag(b);
1079 }
1080
1081 void DirectDrawSurface::setHasAlphaFlag(bool b)
1082 {
1083         header.setHasAlphaFlag(b);
1084 }
1085
1086 void DirectDrawSurface::setUserVersion(int version)
1087 {
1088     header.setUserVersion(version);
1089 }
1090
1091 void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap)
1092 {
1093         stream.seek(offset(face, mipmap));
1094         
1095         uint w = width();
1096         uint h = height();
1097         
1098         // Compute width and height.
1099         for (uint m = 0; m < mipmap; m++)
1100         {
1101                 w = max(1U, w / 2);
1102                 h = max(1U, h / 2);
1103         }
1104         
1105         img->allocate(w, h);
1106         
1107         if (hasAlpha())
1108         {
1109                 img->setFormat(Image::Format_ARGB);
1110         }
1111         else
1112         {
1113                 img->setFormat(Image::Format_RGB);
1114         }
1115
1116         if (header.hasDX10Header())
1117         {
1118                 // So far only block formats supported.
1119                 readBlockImage(img);
1120         }
1121         else
1122         {
1123                 if (header.pf.flags & DDPF_RGB) 
1124                 {
1125                         readLinearImage(img);
1126                 }
1127                 else if (header.pf.flags & DDPF_FOURCC)
1128                 {
1129                         readBlockImage(img);
1130                 }
1131         }
1132 }
1133
1134 void DirectDrawSurface::readLinearImage(Image * img)
1135 {
1136         
1137         const uint w = img->width();
1138         const uint h = img->height();
1139         
1140         uint rshift, rsize;
1141         PixelFormat::maskShiftAndSize(header.pf.rmask, &rshift, &rsize);
1142         
1143         uint gshift, gsize;
1144         PixelFormat::maskShiftAndSize(header.pf.gmask, &gshift, &gsize);
1145         
1146         uint bshift, bsize;
1147         PixelFormat::maskShiftAndSize(header.pf.bmask, &bshift, &bsize);
1148         
1149         uint ashift, asize;
1150         PixelFormat::maskShiftAndSize(header.pf.amask, &ashift, &asize);
1151
1152         uint byteCount = (header.pf.bitcount + 7) / 8;
1153
1154         if (byteCount > 4)
1155         {
1156                 /* just in case... we could have segfaults later on if byteCount > 4 */
1157                 printf("DDS: bitcount too large");
1158                 return;
1159         }
1160
1161         // Read linear RGB images.
1162         for (uint y = 0; y < h; y++)
1163         {
1164                 for (uint x = 0; x < w; x++)
1165                 {
1166                         uint c = 0;
1167                         mem_read(stream, (unsigned char *)(&c), byteCount);
1168
1169                         Color32 pixel(0, 0, 0, 0xFF);
1170                         pixel.r = PixelFormat::convert((c & header.pf.rmask) >> rshift, rsize, 8);
1171                         pixel.g = PixelFormat::convert((c & header.pf.gmask) >> gshift, gsize, 8);
1172                         pixel.b = PixelFormat::convert((c & header.pf.bmask) >> bshift, bsize, 8);
1173                         pixel.a = PixelFormat::convert((c & header.pf.amask) >> ashift, asize, 8);
1174
1175                         img->pixel(x, y) = pixel;
1176                 }
1177         }
1178 }
1179
1180 void DirectDrawSurface::readBlockImage(Image * img)
1181 {
1182
1183         const uint w = img->width();
1184         const uint h = img->height();
1185         
1186         const uint bw = (w + 3) / 4;
1187         const uint bh = (h + 3) / 4;
1188         
1189         for (uint by = 0; by < bh; by++)
1190         {
1191                 for (uint bx = 0; bx < bw; bx++)
1192                 {
1193                         ColorBlock block;
1194                         
1195                         // Read color block.
1196                         readBlock(&block);
1197                         
1198                         // Write color block.
1199                         for (uint y = 0; y < min(4U, h-4*by); y++)
1200                         {
1201                                 for (uint x = 0; x < min(4U, w-4*bx); x++)
1202                                 {
1203                                         img->pixel(4*bx+x, 4*by+y) = block.color(x, y);
1204                                 }
1205                         }
1206                 }
1207         }
1208 }
1209
1210 static Color32 buildNormal(uint8 x, uint8 y)
1211 {
1212         float nx = 2 * (x / 255.0f) - 1;
1213         float ny = 2 * (y / 255.0f) - 1;
1214         float nz = 0.0f;
1215         if (1 - nx*nx - ny*ny > 0) nz = sqrt(1 - nx*nx - ny*ny);
1216         uint8 z = clamp(int(255.0f * (nz + 1) / 2.0f), 0, 255);
1217         
1218         return Color32(x, y, z);
1219 }
1220
1221
1222 void DirectDrawSurface::readBlock(ColorBlock * rgba)
1223 {
1224         uint fourcc = header.pf.fourcc;
1225
1226         // Map DX10 block formats to fourcc codes.
1227         if (header.hasDX10Header())
1228         {
1229                 if (header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM) fourcc = FOURCC_DXT1;
1230                 if (header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM) fourcc = FOURCC_DXT3;
1231                 if (header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM) fourcc = FOURCC_DXT5;
1232                 if (header.header10.dxgiFormat == DXGI_FORMAT_BC4_UNORM) fourcc = FOURCC_ATI1;
1233                 if (header.header10.dxgiFormat == DXGI_FORMAT_BC5_UNORM) fourcc = FOURCC_ATI2;
1234         }
1235
1236
1237         if (fourcc == FOURCC_DXT1)
1238         {
1239                 BlockDXT1 block;
1240                 mem_read(stream, block);
1241                 block.decodeBlock(rgba);
1242         }
1243         else if (fourcc == FOURCC_DXT2 ||
1244             header.pf.fourcc == FOURCC_DXT3)
1245         {
1246                 BlockDXT3 block;
1247                 mem_read(stream, block);
1248                 block.decodeBlock(rgba);
1249         }
1250         else if (fourcc == FOURCC_DXT4 ||
1251             header.pf.fourcc == FOURCC_DXT5 ||
1252             header.pf.fourcc == FOURCC_RXGB)
1253         {
1254                 BlockDXT5 block;
1255                 mem_read(stream, block);
1256                 block.decodeBlock(rgba);
1257                 
1258                 if (fourcc == FOURCC_RXGB)
1259                 {
1260                         // Swap R & A.
1261                         for (int i = 0; i < 16; i++)
1262                         {
1263                                 Color32 & c = rgba->color(i);
1264                                 uint tmp = c.r;
1265                                 c.r = c.a;
1266                                 c.a = tmp;
1267                         }
1268                 }
1269         }
1270         else if (fourcc == FOURCC_ATI1)
1271         {
1272                 BlockATI1 block;
1273                 mem_read(stream, block);
1274                 block.decodeBlock(rgba);
1275         }
1276         else if (fourcc == FOURCC_ATI2)
1277         {
1278                 BlockATI2 block;
1279                 mem_read(stream, block);
1280                 block.decodeBlock(rgba);
1281         }
1282         
1283         // If normal flag set, convert to normal.
1284         if (header.pf.flags & DDPF_NORMAL)
1285         {
1286                 if (fourcc == FOURCC_ATI2)
1287                 {
1288                         for (int i = 0; i < 16; i++)
1289                         {
1290                                 Color32 & c = rgba->color(i);
1291                                 c = buildNormal(c.r, c.g);
1292                         }
1293                 }
1294                 else if (fourcc == FOURCC_DXT5)
1295                 {
1296                         for (int i = 0; i < 16; i++)
1297                         {
1298                                 Color32 & c = rgba->color(i);
1299                                 c = buildNormal(c.a, c.g);
1300                         }
1301                 }
1302         }
1303 }
1304
1305
1306 uint DirectDrawSurface::blockSize() const
1307 {
1308         switch(header.pf.fourcc)
1309         {
1310                 case FOURCC_DXT1:
1311                 case FOURCC_ATI1:
1312                         return 8;
1313                 case FOURCC_DXT2:
1314                 case FOURCC_DXT3:
1315                 case FOURCC_DXT4:
1316                 case FOURCC_DXT5:
1317                 case FOURCC_RXGB:
1318                 case FOURCC_ATI2:
1319                         return 16;
1320                 case FOURCC_DX10:
1321                         switch(header.header10.dxgiFormat)
1322                         {
1323                                 case DXGI_FORMAT_BC1_TYPELESS:
1324                                 case DXGI_FORMAT_BC1_UNORM:
1325                                 case DXGI_FORMAT_BC1_UNORM_SRGB:
1326                                 case DXGI_FORMAT_BC4_TYPELESS:
1327                                 case DXGI_FORMAT_BC4_UNORM:
1328                                 case DXGI_FORMAT_BC4_SNORM:
1329                                         return 8;
1330                                 case DXGI_FORMAT_BC2_TYPELESS:
1331                                 case DXGI_FORMAT_BC2_UNORM:
1332                                 case DXGI_FORMAT_BC2_UNORM_SRGB:
1333                                 case DXGI_FORMAT_BC3_TYPELESS:
1334                                 case DXGI_FORMAT_BC3_UNORM:
1335                                 case DXGI_FORMAT_BC3_UNORM_SRGB:
1336                                 case DXGI_FORMAT_BC5_TYPELESS:
1337                                 case DXGI_FORMAT_BC5_UNORM:
1338                                 case DXGI_FORMAT_BC5_SNORM:
1339                                         return 16;
1340                         };
1341         };
1342
1343         // Not a block image.
1344         return 0;
1345 }
1346
1347 uint DirectDrawSurface::mipmapSize(uint mipmap) const
1348 {
1349         uint w = width();
1350         uint h = height();
1351         uint d = depth();
1352         
1353         for (uint m = 0; m < mipmap; m++)
1354         {
1355                 w = max(1U, w / 2);
1356                 h = max(1U, h / 2);
1357                 d = max(1U, d / 2);
1358         }
1359
1360         if (header.pf.flags & DDPF_FOURCC)
1361         {
1362                 // @@ How are 3D textures aligned?
1363                 w = (w + 3) / 4;
1364                 h = (h + 3) / 4;
1365                 return blockSize() * w * h;
1366         }
1367         else if (header.pf.flags & DDPF_RGB || (header.pf.flags & DDPF_LUMINANCE))
1368         {
1369         uint pitch = computePitch(w, header.pf.bitcount, 8); // Asuming 8 bit alignment, which is the same D3DX expects.
1370         
1371                 return pitch * h * d;
1372         }
1373         else {
1374                 printf("DDS: mipmap format not supported\n");
1375                 return(0);
1376         };
1377 }
1378
1379 uint DirectDrawSurface::faceSize() const
1380 {
1381         const uint count = mipmapCount();
1382         uint size = 0;
1383         
1384         for (uint m = 0; m < count; m++)
1385         {
1386                 size += mipmapSize(m);
1387         }
1388         
1389         return size;
1390 }
1391
1392 uint DirectDrawSurface::offset(const uint face, const uint mipmap)
1393 {
1394         uint size = 128; // sizeof(DDSHeader);
1395         
1396         if (header.hasDX10Header())
1397         {
1398                 size += 20; // sizeof(DDSHeader10);
1399         }
1400
1401         if (face != 0)
1402         {
1403                 size += face * faceSize();
1404         }
1405         
1406         for (uint m = 0; m < mipmap; m++)
1407         {
1408                 size += mipmapSize(m);
1409         }
1410         
1411         return size;
1412 }
1413
1414
1415 void DirectDrawSurface::printInfo() const
1416 {
1417         printf("Flags: 0x%.8X\n", header.flags);
1418         if (header.flags & DDSD_CAPS) printf("\tDDSD_CAPS\n");
1419         if (header.flags & DDSD_PIXELFORMAT) printf("\tDDSD_PIXELFORMAT\n");
1420         if (header.flags & DDSD_WIDTH) printf("\tDDSD_WIDTH\n");
1421         if (header.flags & DDSD_HEIGHT) printf("\tDDSD_HEIGHT\n");
1422         if (header.flags & DDSD_DEPTH) printf("\tDDSD_DEPTH\n");
1423         if (header.flags & DDSD_PITCH) printf("\tDDSD_PITCH\n");
1424         if (header.flags & DDSD_LINEARSIZE) printf("\tDDSD_LINEARSIZE\n");
1425         if (header.flags & DDSD_MIPMAPCOUNT) printf("\tDDSD_MIPMAPCOUNT\n");
1426
1427         printf("Height: %u\n", header.height);
1428         printf("Width: %u\n", header.width);
1429         printf("Depth: %u\n", header.depth);
1430         if (header.flags & DDSD_PITCH) printf("Pitch: %u\n", header.pitch);
1431         else if (header.flags & DDSD_LINEARSIZE) printf("Linear size: %u\n", header.pitch);
1432         printf("Mipmap count: %u\n", header.mipmapcount);
1433         
1434         printf("Pixel Format:\n");
1435         printf("\tFlags: 0x%.8X\n", header.pf.flags);
1436         if (header.pf.flags & DDPF_RGB) printf("\t\tDDPF_RGB\n");
1437     if (header.pf.flags & DDPF_LUMINANCE) printf("\t\tDDPF_LUMINANCE\n");
1438         if (header.pf.flags & DDPF_FOURCC) printf("\t\tDDPF_FOURCC\n");
1439         if (header.pf.flags & DDPF_ALPHAPIXELS) printf("\t\tDDPF_ALPHAPIXELS\n");
1440         if (header.pf.flags & DDPF_ALPHA) printf("\t\tDDPF_ALPHA\n");
1441         if (header.pf.flags & DDPF_PALETTEINDEXED1) printf("\t\tDDPF_PALETTEINDEXED1\n");
1442         if (header.pf.flags & DDPF_PALETTEINDEXED2) printf("\t\tDDPF_PALETTEINDEXED2\n");
1443         if (header.pf.flags & DDPF_PALETTEINDEXED4) printf("\t\tDDPF_PALETTEINDEXED4\n");
1444         if (header.pf.flags & DDPF_PALETTEINDEXED8) printf("\t\tDDPF_PALETTEINDEXED8\n");
1445         if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n");
1446         if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n");
1447         
1448     if (header.pf.fourcc != 0) { 
1449         // Display fourcc code even when DDPF_FOURCC flag not set.
1450         printf("\tFourCC: '%c%c%c%c' (0x%.8X)\n",
1451                         ((header.pf.fourcc >> 0) & 0xFF),
1452                         ((header.pf.fourcc >> 8) & 0xFF),
1453                         ((header.pf.fourcc >> 16) & 0xFF),
1454             ((header.pf.fourcc >> 24) & 0xFF), 
1455             header.pf.fourcc);
1456     }
1457
1458     if ((header.pf.flags & DDPF_FOURCC) && (header.pf.bitcount != 0))
1459         {
1460         printf("\tSwizzle: '%c%c%c%c' (0x%.8X)\n", 
1461                         (header.pf.bitcount >> 0) & 0xFF,
1462                         (header.pf.bitcount >> 8) & 0xFF,
1463                         (header.pf.bitcount >> 16) & 0xFF,
1464             (header.pf.bitcount >> 24) & 0xFF,
1465             header.pf.bitcount);
1466         }
1467         else
1468         {
1469                 printf("\tBit count: %u\n", header.pf.bitcount);
1470         }
1471
1472         printf("\tRed mask: 0x%.8X\n", header.pf.rmask);
1473         printf("\tGreen mask: 0x%.8X\n", header.pf.gmask);
1474         printf("\tBlue mask: 0x%.8X\n", header.pf.bmask);
1475         printf("\tAlpha mask: 0x%.8X\n", header.pf.amask);
1476
1477         printf("Caps:\n");
1478         printf("\tCaps 1: 0x%.8X\n", header.caps.caps1);
1479         if (header.caps.caps1 & DDSCAPS_COMPLEX) printf("\t\tDDSCAPS_COMPLEX\n");
1480         if (header.caps.caps1 & DDSCAPS_TEXTURE) printf("\t\tDDSCAPS_TEXTURE\n");
1481         if (header.caps.caps1 & DDSCAPS_MIPMAP) printf("\t\tDDSCAPS_MIPMAP\n");
1482
1483         printf("\tCaps 2: 0x%.8X\n", header.caps.caps2);
1484         if (header.caps.caps2 & DDSCAPS2_VOLUME) printf("\t\tDDSCAPS2_VOLUME\n");
1485         else if (header.caps.caps2 & DDSCAPS2_CUBEMAP)
1486         {
1487                 printf("\t\tDDSCAPS2_CUBEMAP\n");
1488                 if ((header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) == DDSCAPS2_CUBEMAP_ALL_FACES) printf("\t\tDDSCAPS2_CUBEMAP_ALL_FACES\n");
1489                 else {
1490                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEX\n");
1491                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEX\n");
1492                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEY\n");
1493                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEY\n");
1494                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEZ\n");
1495                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEZ\n");
1496                 }
1497         }
1498
1499         printf("\tCaps 3: 0x%.8X\n", header.caps.caps3);
1500         printf("\tCaps 4: 0x%.8X\n", header.caps.caps4);
1501
1502         if (header.hasDX10Header())
1503         {
1504                 printf("DX10 Header:\n");
1505                 printf("\tDXGI Format: %u (%s)\n", header.header10.dxgiFormat, getDxgiFormatString((DXGI_FORMAT)header.header10.dxgiFormat));
1506                 printf("\tResource dimension: %u (%s)\n", header.header10.resourceDimension, getD3d10ResourceDimensionString((D3D10_RESOURCE_DIMENSION)header.header10.resourceDimension));
1507                 printf("\tMisc flag: %u\n", header.header10.miscFlag);
1508                 printf("\tArray size: %u\n", header.header10.arraySize);
1509         }
1510         
1511     if (header.reserved[9] == FOURCC_NVTT)
1512         {
1513                 int major = (header.reserved[10] >> 16) & 0xFF;
1514                 int minor = (header.reserved[10] >> 8) & 0xFF;
1515                 int revision= header.reserved[10] & 0xFF;
1516                 
1517                 printf("Version:\n");
1518                 printf("\tNVIDIA Texture Tools %d.%d.%d\n", major, minor, revision);
1519         }
1520
1521     if (header.reserved[7] == FOURCC_UVER)
1522     {
1523         printf("User Version: %u\n", header.reserved[8]);
1524     }
1525 }
1526