changed sqrtf to sqrt to make solaris and other platforms happy.
[blender.git] / source / blender / imbuf / intern / dds / DirectDrawSurface.cpp
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * Contributors: Amorilia (amorilia@gamebox.net)
24  *
25  * ***** END GPL/BL DUAL LICENSE BLOCK *****
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)((unsigned char)(ch0)) | \
71                 ((uint)((unsigned char)(ch1)) << 8) | \
72                 ((uint)((unsigned char)(ch2)) << 16) | \
73                 ((uint)((unsigned char)(ch3)) << 24 ))
74 #endif
75
76 static const uint FOURCC_DDS = MAKEFOURCC('D', 'D', 'S', ' ');
77 static const uint FOURCC_DXT1 = MAKEFOURCC('D', 'X', 'T', '1');
78 static const uint FOURCC_DXT2 = MAKEFOURCC('D', 'X', 'T', '2');
79 static const uint FOURCC_DXT3 = MAKEFOURCC('D', 'X', 'T', '3');
80 static const uint FOURCC_DXT4 = MAKEFOURCC('D', 'X', 'T', '4');
81 static const uint FOURCC_DXT5 = MAKEFOURCC('D', 'X', 'T', '5');
82 static const uint FOURCC_RXGB = MAKEFOURCC('R', 'X', 'G', 'B');
83 static const uint FOURCC_ATI1 = MAKEFOURCC('A', 'T', 'I', '1');
84 static const uint FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2');
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 static const uint DDPF_NORMAL = 0x80000000U;    // @@ Custom nv flag.
158
159         // DX10 formats.
160         enum DXGI_FORMAT
161         {
162                 DXGI_FORMAT_UNKNOWN = 0,
163                 
164                 DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
165                 DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
166                 DXGI_FORMAT_R32G32B32A32_UINT = 3,
167                 DXGI_FORMAT_R32G32B32A32_SINT = 4,
168                 
169                 DXGI_FORMAT_R32G32B32_TYPELESS = 5,
170                 DXGI_FORMAT_R32G32B32_FLOAT = 6,
171                 DXGI_FORMAT_R32G32B32_UINT = 7,
172                 DXGI_FORMAT_R32G32B32_SINT = 8,
173                 
174                 DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
175                 DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
176                 DXGI_FORMAT_R16G16B16A16_UNORM = 11,
177                 DXGI_FORMAT_R16G16B16A16_UINT = 12,
178                 DXGI_FORMAT_R16G16B16A16_SNORM = 13,
179                 DXGI_FORMAT_R16G16B16A16_SINT = 14,
180                 
181                 DXGI_FORMAT_R32G32_TYPELESS = 15,
182                 DXGI_FORMAT_R32G32_FLOAT = 16,
183                 DXGI_FORMAT_R32G32_UINT = 17,
184                 DXGI_FORMAT_R32G32_SINT = 18,
185                 
186                 DXGI_FORMAT_R32G8X24_TYPELESS = 19,
187                 DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
188                 DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
189                 DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
190                 
191                 DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
192                 DXGI_FORMAT_R10G10B10A2_UNORM = 24,
193                 DXGI_FORMAT_R10G10B10A2_UINT = 25,
194                 
195                 DXGI_FORMAT_R11G11B10_FLOAT = 26,
196                 
197                 DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
198                 DXGI_FORMAT_R8G8B8A8_UNORM = 28,
199                 DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
200                 DXGI_FORMAT_R8G8B8A8_UINT = 30,
201                 DXGI_FORMAT_R8G8B8A8_SNORM = 31,
202                 DXGI_FORMAT_R8G8B8A8_SINT = 32,
203                 
204                 DXGI_FORMAT_R16G16_TYPELESS = 33,
205                 DXGI_FORMAT_R16G16_FLOAT = 34,
206                 DXGI_FORMAT_R16G16_UNORM = 35,
207                 DXGI_FORMAT_R16G16_UINT = 36,
208                 DXGI_FORMAT_R16G16_SNORM = 37,
209                 DXGI_FORMAT_R16G16_SINT = 38,
210                 
211                 DXGI_FORMAT_R32_TYPELESS = 39,
212                 DXGI_FORMAT_D32_FLOAT = 40,
213                 DXGI_FORMAT_R32_FLOAT = 41,
214                 DXGI_FORMAT_R32_UINT = 42,
215                 DXGI_FORMAT_R32_SINT = 43,
216                 
217                 DXGI_FORMAT_R24G8_TYPELESS = 44,
218                 DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
219                 DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
220                 DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
221                 
222                 DXGI_FORMAT_R8G8_TYPELESS = 48,
223                 DXGI_FORMAT_R8G8_UNORM = 49,
224                 DXGI_FORMAT_R8G8_UINT = 50,
225                 DXGI_FORMAT_R8G8_SNORM = 51,
226                 DXGI_FORMAT_R8G8_SINT = 52,
227                 
228                 DXGI_FORMAT_R16_TYPELESS = 53,
229                 DXGI_FORMAT_R16_FLOAT = 54,
230                 DXGI_FORMAT_D16_UNORM = 55,
231                 DXGI_FORMAT_R16_UNORM = 56,
232                 DXGI_FORMAT_R16_UINT = 57,
233                 DXGI_FORMAT_R16_SNORM = 58,
234                 DXGI_FORMAT_R16_SINT = 59,
235                 
236                 DXGI_FORMAT_R8_TYPELESS = 60,
237                 DXGI_FORMAT_R8_UNORM = 61,
238                 DXGI_FORMAT_R8_UINT = 62,
239                 DXGI_FORMAT_R8_SNORM = 63,
240                 DXGI_FORMAT_R8_SINT = 64,
241                 DXGI_FORMAT_A8_UNORM = 65,
242                 
243                 DXGI_FORMAT_R1_UNORM = 66,
244                 
245                 DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
246                 
247                 DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
248                 DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
249                 
250                 DXGI_FORMAT_BC1_TYPELESS = 70,
251                 DXGI_FORMAT_BC1_UNORM = 71,
252                 DXGI_FORMAT_BC1_UNORM_SRGB = 72,
253                 
254                 DXGI_FORMAT_BC2_TYPELESS = 73,
255                 DXGI_FORMAT_BC2_UNORM = 74,
256                 DXGI_FORMAT_BC2_UNORM_SRGB = 75,
257                 
258                 DXGI_FORMAT_BC3_TYPELESS = 76,
259                 DXGI_FORMAT_BC3_UNORM = 77,
260                 DXGI_FORMAT_BC3_UNORM_SRGB = 78,
261                 
262                 DXGI_FORMAT_BC4_TYPELESS = 79,
263                 DXGI_FORMAT_BC4_UNORM = 80,
264                 DXGI_FORMAT_BC4_SNORM = 81,
265                 
266                 DXGI_FORMAT_BC5_TYPELESS = 82,
267                 DXGI_FORMAT_BC5_UNORM = 83,
268                 DXGI_FORMAT_BC5_SNORM = 84,
269                 
270                 DXGI_FORMAT_B5G6R5_UNORM = 85,
271                 DXGI_FORMAT_B5G5R5A1_UNORM = 86,
272                 DXGI_FORMAT_B8G8R8A8_UNORM = 87,
273                 DXGI_FORMAT_B8G8R8X8_UNORM = 88,
274         };
275
276         enum D3D10_RESOURCE_DIMENSION
277         {
278                 D3D10_RESOURCE_DIMENSION_UNKNOWN = 0,
279                 D3D10_RESOURCE_DIMENSION_BUFFER = 1,
280                 D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2,
281                 D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3,
282                 D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4,
283         };
284
285 /*** implementation ***/
286
287 void mem_read(Stream & mem, DDSPixelFormat & pf)
288 {
289         mem_read(mem, pf.size);
290         mem_read(mem, pf.flags);
291         mem_read(mem, pf.fourcc);
292         mem_read(mem, pf.bitcount);
293         mem_read(mem, pf.rmask);
294         mem_read(mem, pf.gmask);
295         mem_read(mem, pf.bmask);
296         mem_read(mem, pf.amask);
297 }
298
299 void mem_read(Stream & mem, DDSCaps & caps)
300 {
301         mem_read(mem, caps.caps1);
302         mem_read(mem, caps.caps2);
303         mem_read(mem, caps.caps3);
304         mem_read(mem, caps.caps4);
305 }
306
307 void mem_read(Stream & mem, DDSHeader10 & header)
308 {
309         mem_read(mem, header.dxgiFormat);
310         mem_read(mem, header.resourceDimension);
311         mem_read(mem, header.miscFlag);
312         mem_read(mem, header.arraySize);
313         mem_read(mem, header.reserved);
314 }
315
316 void mem_read(Stream & mem, DDSHeader & header)
317 {
318         mem_read(mem, header.fourcc);
319         mem_read(mem, header.size);
320         mem_read(mem, header.flags);
321         mem_read(mem, header.height);
322         mem_read(mem, header.width);
323         mem_read(mem, header.pitch);
324         mem_read(mem, header.depth);
325         mem_read(mem, header.mipmapcount);
326         for (uint i = 0; i < 11; i++) mem_read(mem, header.reserved[i]);
327         mem_read(mem, header.pf);
328         mem_read(mem, header.caps);
329         mem_read(mem, header.notused);
330
331         if (header.hasDX10Header())
332         {
333                 mem_read(mem, header.header10);
334         }
335 }
336
337
338
339 DDSHeader::DDSHeader()
340 {
341         this->fourcc = FOURCC_DDS;
342         this->size = 124;
343         this->flags  = (DDSD_CAPS|DDSD_PIXELFORMAT);
344         this->height = 0;
345         this->width = 0;
346         this->pitch = 0;
347         this->depth = 0;
348         this->mipmapcount = 0;
349         for (uint i = 0; i < 11; i++) this->reserved[i] = 0;
350
351         // Store version information on the reserved header attributes.
352         this->reserved[9] = MAKEFOURCC('N', 'V', 'T', 'T');
353         this->reserved[10] = (0 << 16) | (9 << 8) | (5);        // major.minor.revision
354
355         this->pf.size = 32;
356         this->pf.flags = 0;
357         this->pf.fourcc = 0;
358         this->pf.bitcount = 0;
359         this->pf.rmask = 0;
360         this->pf.gmask = 0;
361         this->pf.bmask = 0;
362         this->pf.amask = 0;
363         this->caps.caps1 = DDSCAPS_TEXTURE;
364         this->caps.caps2 = 0;
365         this->caps.caps3 = 0;
366         this->caps.caps4 = 0;
367         this->notused = 0;
368
369         this->header10.dxgiFormat = DXGI_FORMAT_UNKNOWN;
370         this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_UNKNOWN;
371         this->header10.miscFlag = 0;
372         this->header10.arraySize = 0;
373         this->header10.reserved = 0;
374 }
375
376 void DDSHeader::setWidth(uint w)
377 {
378         this->flags |= DDSD_WIDTH;
379         this->width = w;
380 }
381
382 void DDSHeader::setHeight(uint h)
383 {
384         this->flags |= DDSD_HEIGHT;
385         this->height = h;
386 }
387
388 void DDSHeader::setDepth(uint d)
389 {
390         this->flags |= DDSD_DEPTH;
391         this->height = d;
392 }
393
394 void DDSHeader::setMipmapCount(uint count)
395 {
396         if (count == 0 || count == 1)
397         {
398                 this->flags &= ~DDSD_MIPMAPCOUNT;
399                 this->mipmapcount = 0;
400
401                 if (this->caps.caps2 == 0) {
402                         this->caps.caps1 = DDSCAPS_TEXTURE;
403                 }
404                 else {
405                         this->caps.caps1 = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
406                 }
407         }
408         else
409         {
410                 this->flags |= DDSD_MIPMAPCOUNT;
411                 this->mipmapcount = count;
412
413                 this->caps.caps1 |= DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
414         }
415 }
416
417 void DDSHeader::setTexture2D()
418 {
419         this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
420 }
421
422 void DDSHeader::setTexture3D()
423 {
424         this->caps.caps2 = DDSCAPS2_VOLUME;
425
426         this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D;
427 }
428
429 void DDSHeader::setTextureCube()
430 {
431         this->caps.caps1 |= DDSCAPS_COMPLEX;
432         this->caps.caps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALL_FACES;
433
434         this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
435         this->header10.arraySize = 6;
436 }
437
438 void DDSHeader::setLinearSize(uint size)
439 {
440         this->flags &= ~DDSD_PITCH;
441         this->flags |= DDSD_LINEARSIZE;
442         this->pitch = size;
443 }
444
445 void DDSHeader::setPitch(uint pitch)
446 {
447         this->flags &= ~DDSD_LINEARSIZE;
448         this->flags |= DDSD_PITCH;
449         this->pitch = pitch;
450 }
451
452 void DDSHeader::setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3)
453 {
454         // set fourcc pixel format.
455         this->pf.flags = DDPF_FOURCC;
456         this->pf.fourcc = MAKEFOURCC(c0, c1, c2, c3);
457         this->pf.bitcount = 0;
458         this->pf.rmask = 0;
459         this->pf.gmask = 0;
460         this->pf.bmask = 0;
461         this->pf.amask = 0;
462 }
463
464 void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
465 {
466         // Make sure the masks are correct.
467         if ((rmask & gmask) || \
468                 (rmask & bmask) || \
469                 (rmask & amask) || \
470                 (gmask & bmask) || \
471                 (gmask & amask) || \
472                 (bmask & amask)) {
473                 printf("DDS: bad RGBA masks, pixel format not set\n");
474                 return;
475         }
476
477         this->pf.flags = DDPF_RGB;
478
479         if (amask != 0) {
480                 this->pf.flags |= DDPF_ALPHAPIXELS;
481         }
482
483         if (bitcount == 0)
484         {
485                 // Compute bit count from the masks.
486                 uint total = rmask | gmask | bmask | amask;
487                 while(total != 0) {
488                         bitcount++;
489                         total >>= 1;
490                 }
491         }
492
493         if (!(bitcount > 0 && bitcount <= 32)) {
494                 printf("DDS: bad bit count, pixel format not set\n");
495                 return;
496         }
497
498         // Align to 8.
499         if (bitcount < 8) bitcount = 8;
500         else if (bitcount < 16) bitcount = 16;
501         else if (bitcount < 24) bitcount = 24;
502         else bitcount = 32;
503
504         this->pf.fourcc = 0; //findD3D9Format(bitcount, rmask, gmask, bmask, amask);
505         this->pf.bitcount = bitcount;
506         this->pf.rmask = rmask;
507         this->pf.gmask = gmask;
508         this->pf.bmask = bmask;
509         this->pf.amask = amask;
510 }
511
512 void DDSHeader::setDX10Format(uint format)
513 {
514         this->pf.flags = 0;
515         this->header10.dxgiFormat = format;
516 }
517
518 void DDSHeader::setNormalFlag(bool b)
519 {
520         if (b) this->pf.flags |= DDPF_NORMAL;
521         else this->pf.flags &= ~DDPF_NORMAL;
522 }
523
524 bool DDSHeader::hasDX10Header() const
525 {
526         return this->pf.flags == 0;
527 }
528
529 DirectDrawSurface::DirectDrawSurface(unsigned char *mem, uint size) : stream(mem, size), header()
530 {
531         mem_read(stream, header);
532 }
533
534 DirectDrawSurface::~DirectDrawSurface()
535 {
536 }
537
538 bool DirectDrawSurface::isValid() const
539 {
540         if (header.fourcc != FOURCC_DDS || header.size != 124)
541         {
542                 return false;
543         }
544         
545         const uint required = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|DDSD_PIXELFORMAT);
546         if( (header.flags & required) != required ) {
547                 return false;
548         }
549         
550         if (header.pf.size != 32) {
551                 return false;
552         }
553
554         /* in some files DDSCAPS_TEXTURE is missing: silently ignore */
555         /*
556         if( !(header.caps.caps1 & DDSCAPS_TEXTURE) ) {
557                 return false;
558         }
559         */
560
561         return true;
562 }
563
564 bool DirectDrawSurface::isSupported() const
565 {
566         if (header.pf.flags & DDPF_FOURCC)
567         {
568                 if (header.pf.fourcc != FOURCC_DXT1 &&
569                     header.pf.fourcc != FOURCC_DXT2 &&
570                     header.pf.fourcc != FOURCC_DXT3 &&
571                     header.pf.fourcc != FOURCC_DXT4 &&
572                     header.pf.fourcc != FOURCC_DXT5 &&
573                     header.pf.fourcc != FOURCC_RXGB &&
574                     header.pf.fourcc != FOURCC_ATI1 &&
575                     header.pf.fourcc != FOURCC_ATI2)
576                 {
577                         // Unknown fourcc code.
578                         return false;
579                 }
580         }
581         else if (header.pf.flags & DDPF_RGB)
582         {
583                 // All RGB formats are supported now.
584         }
585         else
586         {
587                 return false;
588         }
589         
590         if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES)
591         {
592                 // Cubemaps must contain all faces.
593                 return false;
594         }
595         
596         if (isTexture3D())
597         {
598                 // @@ 3D textures not supported yet.
599                 return false;
600         }
601         
602         return true;
603 }
604
605
606 uint DirectDrawSurface::mipmapCount() const
607 {
608         if (header.flags & DDSD_MIPMAPCOUNT) return header.mipmapcount;
609         else return 0;
610 }
611
612
613 uint DirectDrawSurface::width() const
614 {
615         if (header.flags & DDSD_WIDTH) return header.width;
616         else return 1;
617 }
618
619 uint DirectDrawSurface::height() const
620 {
621         if (header.flags & DDSD_HEIGHT) return header.height;
622         else return 1;
623 }
624
625 uint DirectDrawSurface::depth() const
626 {
627         if (header.flags & DDSD_DEPTH) return header.depth;
628         else return 1;
629 }
630
631 bool DirectDrawSurface::hasAlpha() const
632 {
633         if ((header.pf.flags & DDPF_RGB) && (header.pf.amask == 0))
634         {
635                 return false;
636         }
637         else if (header.pf.fourcc == FOURCC_DXT1)
638         {
639                 return false;
640         }
641         else
642         {
643                 return true;
644         }
645 }
646
647 bool DirectDrawSurface::isTexture2D() const
648 {
649         return !isTexture3D() && !isTextureCube();
650 }
651
652 bool DirectDrawSurface::isTexture3D() const
653 {
654         return (header.caps.caps2 & DDSCAPS2_VOLUME) != 0;
655 }
656
657 bool DirectDrawSurface::isTextureCube() const
658 {
659         return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0;
660 }
661
662 void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap)
663 {
664         stream.seek(offset(face, mipmap));
665         
666         uint w = width();
667         uint h = height();
668         
669         // Compute width and height.
670         for (uint m = 0; m < mipmap; m++)
671         {
672                 w = max(1U, w / 2);
673                 h = max(1U, h / 2);
674         }
675         
676         img->allocate(w, h);
677         
678         if (header.pf.flags & DDPF_RGB) 
679         {
680                 readLinearImage(img);
681         }
682         else if (header.pf.flags & DDPF_FOURCC)
683         {
684                 readBlockImage(img);
685         }
686 }
687
688 void DirectDrawSurface::readLinearImage(Image * img)
689 {
690         
691         const uint w = img->width();
692         const uint h = img->height();
693         
694         uint rshift, rsize;
695         PixelFormat::maskShiftAndSize(header.pf.rmask, &rshift, &rsize);
696         
697         uint gshift, gsize;
698         PixelFormat::maskShiftAndSize(header.pf.gmask, &gshift, &gsize);
699         
700         uint bshift, bsize;
701         PixelFormat::maskShiftAndSize(header.pf.bmask, &bshift, &bsize);
702         
703         uint ashift, asize;
704         PixelFormat::maskShiftAndSize(header.pf.amask, &ashift, &asize);
705
706         uint byteCount = (header.pf.bitcount + 7) / 8;
707
708         if (byteCount > 4)
709         {
710                 /* just in case... we could have segfaults later on if byteCount > 4 */
711                 printf("DDS: bitcount too large");
712                 return;
713         }
714
715         if (header.pf.amask != 0)
716         {
717                 img->setFormat(Image::Format_ARGB);
718         }
719
720         // Read linear RGB images.
721         for (uint y = 0; y < h; y++)
722         {
723                 for (uint x = 0; x < w; x++)
724                 {
725                         uint c = 0;
726                         mem_read(stream, (unsigned char *)(&c), byteCount);
727
728                         Color32 pixel(0, 0, 0, 0xFF);
729                         pixel.r = PixelFormat::convert(c >> rshift, rsize, 8);
730                         pixel.g = PixelFormat::convert(c >> gshift, gsize, 8);
731                         pixel.b = PixelFormat::convert(c >> bshift, bsize, 8);
732                         pixel.a = PixelFormat::convert(c >> ashift, asize, 8);
733
734                         img->pixel(x, y) = pixel;
735                 }
736         }
737 }
738
739 void DirectDrawSurface::readBlockImage(Image * img)
740 {
741         const uint w = img->width();
742         const uint h = img->height();
743         
744         const uint bw = (w + 3) / 4;
745         const uint bh = (h + 3) / 4;
746         
747         for (uint by = 0; by < bh; by++)
748         {
749                 for (uint bx = 0; bx < bw; bx++)
750                 {
751                         ColorBlock block;
752                         
753                         // Read color block.
754                         readBlock(&block);
755                         
756                         // Write color block.
757                         for (uint y = 0; y < min(4U, h-4*by); y++)
758                         {
759                                 for (uint x = 0; x < min(4U, w-4*bx); x++)
760                                 {
761                                         img->pixel(4*bx+x, 4*by+y) = block.color(x, y);
762                                 }
763                         }
764                 }
765         }
766 }
767
768 static Color32 buildNormal(uint8 x, uint8 y)
769 {
770         float nx = 2 * (x / 255.0f) - 1;
771         float ny = 2 * (y / 255.0f) - 1;
772         float nz = 0.0f;
773         if (1 - nx*nx - ny*ny > 0) nz = sqrt(1 - nx*nx - ny*ny);
774         uint8 z = clamp(int(255.0f * (nz + 1) / 2.0f), 0, 255);
775         
776         return Color32(x, y, z);
777 }
778
779
780 void DirectDrawSurface::readBlock(ColorBlock * rgba)
781 {
782         if (header.pf.fourcc == FOURCC_DXT1)
783         {
784                 BlockDXT1 block;
785                 mem_read(stream, block);
786                 block.decodeBlock(rgba);
787         }
788         else if (header.pf.fourcc == FOURCC_DXT2 ||
789             header.pf.fourcc == FOURCC_DXT3)
790         {
791                 BlockDXT3 block;
792                 mem_read(stream, block);
793                 block.decodeBlock(rgba);
794         }
795         else if (header.pf.fourcc == FOURCC_DXT4 ||
796             header.pf.fourcc == FOURCC_DXT5 ||
797             header.pf.fourcc == FOURCC_RXGB)
798         {
799                 BlockDXT5 block;
800                 mem_read(stream, block);
801                 block.decodeBlock(rgba);
802                 
803                 if (header.pf.fourcc == FOURCC_RXGB)
804                 {
805                         // Swap R & A.
806                         for (int i = 0; i < 16; i++)
807                         {
808                                 Color32 & c = rgba->color(i);
809                                 uint tmp = c.r;
810                                 c.r = c.a;
811                                 c.a = tmp;
812                         }
813                 }
814         }
815         else if (header.pf.fourcc == FOURCC_ATI1)
816         {
817                 BlockATI1 block;
818                 mem_read(stream, block);
819                 block.decodeBlock(rgba);
820         }
821         else if (header.pf.fourcc == FOURCC_ATI2)
822         {
823                 BlockATI2 block;
824                 mem_read(stream, block);
825                 block.decodeBlock(rgba);
826         }
827         
828         // If normal flag set, convert to normal.
829         if (header.pf.flags & DDPF_NORMAL)
830         {
831                 if (header.pf.fourcc == FOURCC_ATI2)
832                 {
833                         for (int i = 0; i < 16; i++)
834                         {
835                                 Color32 & c = rgba->color(i);
836                                 c = buildNormal(c.r, c.g);
837                         }
838                 }
839                 else if (header.pf.fourcc == FOURCC_DXT5)
840                 {
841                         for (int i = 0; i < 16; i++)
842                         {
843                                 Color32 & c = rgba->color(i);
844                                 c = buildNormal(c.a, c.g);
845                         }
846                 }
847         }
848 }
849
850
851 uint DirectDrawSurface::blockSize() const
852 {
853         switch(header.pf.fourcc)
854         {
855                 case FOURCC_DXT1:
856                 case FOURCC_ATI1:
857                         return 8;
858                 case FOURCC_DXT2:
859                 case FOURCC_DXT3:
860                 case FOURCC_DXT4:
861                 case FOURCC_DXT5:
862                 case FOURCC_RXGB:
863                 case FOURCC_ATI2:
864                         return 16;
865         };
866
867         // Not a block image.
868         return 0;
869 }
870
871 uint DirectDrawSurface::mipmapSize(uint mipmap) const
872 {
873         uint w = width();
874         uint h = height();
875         uint d = depth();
876         
877         for (uint m = 0; m < mipmap; m++)
878         {
879                 w = max(1U, w / 2);
880                 h = max(1U, h / 2);
881                 d = max(1U, d / 2);
882         }
883
884         if (header.pf.flags & DDPF_FOURCC)
885         {
886                 // @@ How are 3D textures aligned?
887                 w = (w + 3) / 4;
888                 h = (h + 3) / 4;
889                 return blockSize() * w * h;
890         }
891         else if (header.pf.flags & DDPF_RGB)
892         {
893                 // Align pixels to bytes.
894                 uint byteCount = (header.pf.bitcount + 7) / 8;
895                 
896                 // Align pitch to 4 bytes.
897                 uint pitch = 4 * ((w * byteCount + 3) / 4);
898                 
899                 return pitch * h * d;
900         }
901         else {
902                 printf("DDS: mipmap format not supported\n");
903                 return(0);
904         };
905 }
906
907 uint DirectDrawSurface::faceSize() const
908 {
909         const uint count = mipmapCount();
910         uint size = 0;
911         
912         for (uint m = 0; m < count; m++)
913         {
914                 size += mipmapSize(m);
915         }
916         
917         return size;
918 }
919
920 uint DirectDrawSurface::offset(const uint face, const uint mipmap)
921 {
922         uint size = 128; //sizeof(DDSHeader);
923         
924         if (face != 0)
925         {
926                 size += face * faceSize();
927         }
928         
929         for (uint m = 0; m < mipmap; m++)
930         {
931                 size += mipmapSize(m);
932         }
933         
934         return size;
935 }
936
937
938 void DirectDrawSurface::printInfo() const
939 {
940         /* printf("FOURCC: %c%c%c%c\n", ((unsigned char *)&header.fourcc)[0], ((unsigned char *)&header.fourcc)[1], ((unsigned char *)&header.fourcc)[2], ((unsigned char *)&header.fourcc)[3]); */
941         printf("Flags: 0x%.8X\n", header.flags);
942         if (header.flags & DDSD_CAPS) printf("\tDDSD_CAPS\n");
943         if (header.flags & DDSD_PIXELFORMAT) printf("\tDDSD_PIXELFORMAT\n");
944         if (header.flags & DDSD_WIDTH) printf("\tDDSD_WIDTH\n");
945         if (header.flags & DDSD_HEIGHT) printf("\tDDSD_HEIGHT\n");
946         if (header.flags & DDSD_DEPTH) printf("\tDDSD_DEPTH\n");
947         if (header.flags & DDSD_PITCH) printf("\tDDSD_PITCH\n");
948         if (header.flags & DDSD_LINEARSIZE) printf("\tDDSD_LINEARSIZE\n");
949         if (header.flags & DDSD_MIPMAPCOUNT) printf("\tDDSD_MIPMAPCOUNT\n");
950
951         printf("Height: %d\n", header.height);
952         printf("Width: %d\n", header.width);
953         printf("Depth: %d\n", header.depth);
954         if (header.flags & DDSD_PITCH) printf("Pitch: %d\n", header.pitch);
955         else if (header.flags & DDSD_LINEARSIZE) printf("Linear size: %d\n", header.pitch);
956         printf("Mipmap count: %d\n", header.mipmapcount);
957         
958         printf("Pixel Format:\n");
959         /* printf("\tSize: %d\n", header.pf.size); */
960         printf("\tFlags: 0x%.8X\n", header.pf.flags);
961         if (header.pf.flags & DDPF_RGB) printf("\t\tDDPF_RGB\n");
962         if (header.pf.flags & DDPF_FOURCC) printf("\t\tDDPF_FOURCC\n");
963         if (header.pf.flags & DDPF_ALPHAPIXELS) printf("\t\tDDPF_ALPHAPIXELS\n");
964         if (header.pf.flags & DDPF_ALPHA) printf("\t\tDDPF_ALPHA\n");
965         if (header.pf.flags & DDPF_PALETTEINDEXED1) printf("\t\tDDPF_PALETTEINDEXED1\n");
966         if (header.pf.flags & DDPF_PALETTEINDEXED2) printf("\t\tDDPF_PALETTEINDEXED2\n");
967         if (header.pf.flags & DDPF_PALETTEINDEXED4) printf("\t\tDDPF_PALETTEINDEXED4\n");
968         if (header.pf.flags & DDPF_PALETTEINDEXED8) printf("\t\tDDPF_PALETTEINDEXED8\n");
969         if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n");
970         if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n");
971         
972         printf("\tFourCC: '%c%c%c%c'\n", ((header.pf.fourcc >> 0) & 0xFF), ((header.pf.fourcc >> 8) & 0xFF), ((header.pf.fourcc >> 16) & 0xFF), ((header.pf.fourcc >> 24) & 0xFF));
973         printf("\tBit count: %d\n", header.pf.bitcount);
974         printf("\tRed mask: 0x%.8X\n", header.pf.rmask);
975         printf("\tGreen mask: 0x%.8X\n", header.pf.gmask);
976         printf("\tBlue mask: 0x%.8X\n", header.pf.bmask);
977         printf("\tAlpha mask: 0x%.8X\n", header.pf.amask);
978
979         printf("Caps:\n");
980         printf("\tCaps 1: 0x%.8X\n", header.caps.caps1);
981         if (header.caps.caps1 & DDSCAPS_COMPLEX) printf("\t\tDDSCAPS_COMPLEX\n");
982         if (header.caps.caps1 & DDSCAPS_TEXTURE) printf("\t\tDDSCAPS_TEXTURE\n");
983         if (header.caps.caps1 & DDSCAPS_MIPMAP) printf("\t\tDDSCAPS_MIPMAP\n");
984
985         printf("\tCaps 2: 0x%.8X\n", header.caps.caps2);
986         if (header.caps.caps2 & DDSCAPS2_VOLUME) printf("\t\tDDSCAPS2_VOLUME\n");
987         else if (header.caps.caps2 & DDSCAPS2_CUBEMAP)
988         {
989                 printf("\t\tDDSCAPS2_CUBEMAP\n");
990                 if ((header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) == DDSCAPS2_CUBEMAP_ALL_FACES) printf("\t\tDDSCAPS2_CUBEMAP_ALL_FACES\n");
991                 else {
992                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEX\n");
993                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEX\n");
994                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEY\n");
995                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEY\n");
996                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEZ\n");
997                         if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEZ\n");
998                 }
999         }
1000
1001         printf("\tCaps 3: 0x%.8X\n", header.caps.caps3);
1002         printf("\tCaps 4: 0x%.8X\n", header.caps.caps4);
1003
1004         if (header.pf.flags == 0)
1005         {
1006                 printf("DX10 Header:\n");
1007                 printf("\tDXGI Format: %u\n", header.header10.dxgiFormat);
1008                 printf("\tResource dimension: %u\n", header.header10.resourceDimension);
1009                 printf("\tMisc flag: %u\n", header.header10.miscFlag);
1010                 printf("\tArray size: %u\n", header.header10.arraySize);
1011         }
1012         
1013         if (header.reserved[9] == MAKEFOURCC('N', 'V', 'T', 'T'))
1014         {
1015                 int major = (header.reserved[10] >> 16) & 0xFF;
1016                 int minor = (header.reserved[10] >> 8) & 0xFF;
1017                 int revision= header.reserved[10] & 0xFF;
1018                 
1019                 printf("Version:\n");
1020                 printf("\tNVIDIA Texture Tools %d.%d.%d\n", major, minor, revision);
1021         }
1022 }
1023