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