Apply second half of [#21590] .dds textures: fix for DXT1n format + sync with upstrea...
[blender.git] / source / blender / imbuf / intern / dds / DirectDrawSurface.cpp
index b179432da4a9e9cfbe6fcd18276db683bbc87c3d..ceac1d2ae18154c33571fa57f2ef88edd7306b5f 100644 (file)
 
 #if !defined(MAKEFOURCC)
 #      define MAKEFOURCC(ch0, ch1, ch2, ch3) \
-               ((uint)((unsigned char)(ch0)) | \
-               ((uint)((unsigned char)(ch1)) << 8) | \
-               ((uint)((unsigned char)(ch2)) << 16) | \
-               ((uint)((unsigned char)(ch3)) << 24 ))
+    (uint(uint8(ch0)) | (uint(uint8(ch1)) << 8) | \
+    (uint(uint8(ch2)) << 16) | (uint(uint8(ch3)) << 24 ))
 #endif
 
+static const uint FOURCC_NVTT = MAKEFOURCC('N', 'V', 'T', 'T');
 static const uint FOURCC_DDS = MAKEFOURCC('D', 'D', 'S', ' ');
 static const uint FOURCC_DXT1 = MAKEFOURCC('D', 'X', 'T', '1');
 static const uint FOURCC_DXT2 = MAKEFOURCC('D', 'X', 'T', '2');
@@ -89,6 +88,8 @@ static const uint FOURCC_A2XY = MAKEFOURCC('A', '2', 'X', 'Y');
        
 static const uint FOURCC_DX10 = MAKEFOURCC('D', 'X', '1', '0');
 
+static const uint FOURCC_UVER = MAKEFOURCC('U', 'V', 'E', 'R');
+
 // 32 bit RGB formats.
 static const uint D3DFMT_R8G8B8 = 20;
 static const uint D3DFMT_A8R8G8B8 = 21;
@@ -160,7 +161,10 @@ static const uint DDPF_PALETTEINDEXED4 = 0x00000008U;
 static const uint DDPF_PALETTEINDEXED8 = 0x00000020U;
 static const uint DDPF_LUMINANCE = 0x00020000U;
 static const uint DDPF_ALPHAPREMULT = 0x00008000U;
-static const uint DDPF_NORMAL = 0x80000000U;   // @@ Custom nv flag.
+
+// Custom NVTT flags.
+static const uint DDPF_NORMAL = 0x80000000U;  
+static const uint DDPF_SRGB = 0x40000000U;
 
        // DX10 formats.
        enum DXGI_FORMAT
@@ -277,6 +281,20 @@ static const uint DDPF_NORMAL = 0x80000000U;       // @@ Custom nv flag.
                DXGI_FORMAT_B5G5R5A1_UNORM = 86,
                DXGI_FORMAT_B8G8R8A8_UNORM = 87,
                DXGI_FORMAT_B8G8R8X8_UNORM = 88,
+
+        DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89,
+        DXGI_FORMAT_B8G8R8A8_TYPELESS = 90,
+        DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91,
+        DXGI_FORMAT_B8G8R8X8_TYPELESS = 92,
+        DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93,
+
+        DXGI_FORMAT_BC6H_TYPELESS = 94,
+        DXGI_FORMAT_BC6H_UF16 = 95,
+        DXGI_FORMAT_BC6H_SF16 = 96,
+
+        DXGI_FORMAT_BC7_TYPELESS = 97,
+        DXGI_FORMAT_BC7_UNORM = 98,
+        DXGI_FORMAT_BC7_UNORM_SRGB = 99,
        };
 
        enum D3D10_RESOURCE_DIMENSION
@@ -478,6 +496,63 @@ void mem_read(Stream & mem, DDSHeader & header)
        }
 }
 
+namespace
+{
+    struct FormatDescriptor
+    {
+        uint format;
+        uint bitcount;
+        uint rmask;
+        uint gmask;
+        uint bmask;
+        uint amask;
+    };
+
+    static const FormatDescriptor s_d3dFormats[] =
+    {
+        { D3DFMT_R8G8B8,               24, 0xFF0000,   0xFF00,     0xFF,       0 },
+        { D3DFMT_A8R8G8B8,             32, 0xFF0000,   0xFF00,     0xFF,       0xFF000000 },  // DXGI_FORMAT_B8G8R8A8_UNORM
+        { D3DFMT_X8R8G8B8,             32, 0xFF0000,   0xFF00,     0xFF,       0 },           // DXGI_FORMAT_B8G8R8X8_UNORM
+        { D3DFMT_R5G6B5,               16,     0xF800,     0x7E0,      0x1F,       0 },           // DXGI_FORMAT_B5G6R5_UNORM
+        { D3DFMT_X1R5G5B5,             16, 0x7C00,     0x3E0,      0x1F,       0 },
+        { D3DFMT_A1R5G5B5,             16, 0x7C00,     0x3E0,      0x1F,       0x8000 },      // DXGI_FORMAT_B5G5R5A1_UNORM
+        { D3DFMT_A4R4G4B4,             16, 0xF00,      0xF0,       0xF,        0xF000 },
+        { D3DFMT_R3G3B2,               8,  0xE0,       0x1C,       0x3,            0 },
+        { D3DFMT_A8,                   8,  0,          0,          0,              8 },           // DXGI_FORMAT_A8_UNORM
+        { D3DFMT_A8R3G3B2,             16, 0xE0,       0x1C,       0x3,        0xFF00 },
+        { D3DFMT_X4R4G4B4,             16, 0xF00,      0xF0,       0xF,        0 },
+        { D3DFMT_A2B10G10R10,  32, 0x3FF,      0xFFC00,    0x3FF00000, 0xC0000000 },  // DXGI_FORMAT_R10G10B10A2
+        { D3DFMT_A8B8G8R8,             32, 0xFF,       0xFF00,     0xFF0000,   0xFF000000 },  // DXGI_FORMAT_R8G8B8A8_UNORM
+        { D3DFMT_X8B8G8R8,             32, 0xFF,       0xFF00,     0xFF0000,   0 },
+        { D3DFMT_G16R16,               32, 0xFFFF,     0xFFFF0000, 0,          0 },           // DXGI_FORMAT_R16G16_UNORM
+        { D3DFMT_A2R10G10B10,  32, 0x3FF00000, 0xFFC00,    0x3FF,      0xC0000000 },
+        { D3DFMT_A2B10G10R10,  32, 0x3FF,      0xFFC00,    0x3FF00000, 0xC0000000 },
+
+        { D3DFMT_L8,                   8,  8,          0,          0,          0 },           // DXGI_FORMAT_R8_UNORM 
+        { D3DFMT_L16,                  16, 16,         0,          0,          0 },           // DXGI_FORMAT_R16_UNORM
+    };
+
+    static const uint s_d3dFormatCount = sizeof(s_d3dFormats) / sizeof(s_d3dFormats[0]);
+
+} // namespace
+
+uint findD3D9Format(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
+{
+    for (int i = 0; i < s_d3dFormatCount; i++)
+        {
+            if (s_d3dFormats[i].bitcount == bitcount &&
+                s_d3dFormats[i].rmask == rmask &&
+                s_d3dFormats[i].gmask == gmask &&
+                s_d3dFormats[i].bmask == bmask &&
+                s_d3dFormats[i].amask == amask)
+            {
+                return s_d3dFormats[i].format;
+            }
+        }
+
+        return 0;
+    }
+
 
 
 DDSHeader::DDSHeader()
@@ -493,8 +568,8 @@ DDSHeader::DDSHeader()
        for (uint i = 0; i < 11; i++) this->reserved[i] = 0;
 
        // Store version information on the reserved header attributes.
-       this->reserved[9] = MAKEFOURCC('N', 'V', 'T', 'T');
-       this->reserved[10] = (0 << 16) | (9 << 8) | (5);        // major.minor.revision
+    this->reserved[9] = FOURCC_NVTT;
+       this->reserved[10] = (2 << 16) | (1 << 8) | (0);        // major.minor.revision
 
        this->pf.size = 32;
        this->pf.flags = 0;
@@ -532,7 +607,7 @@ void DDSHeader::setHeight(uint h)
 void DDSHeader::setDepth(uint d)
 {
        this->flags |= DDSD_DEPTH;
-       this->height = d;
+       this->depth = d;
 }
 
 void DDSHeader::setMipmapCount(uint count)
@@ -540,7 +615,7 @@ void DDSHeader::setMipmapCount(uint count)
        if (count == 0 || count == 1)
        {
                this->flags &= ~DDSD_MIPMAPCOUNT;
-               this->mipmapcount = 0;
+        this->mipmapcount = 1;
 
                if (this->caps.caps2 == 0) {
                        this->caps.caps1 = DDSCAPS_TEXTURE;
@@ -561,6 +636,7 @@ void DDSHeader::setMipmapCount(uint count)
 void DDSHeader::setTexture2D()
 {
        this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
+       this->header10.arraySize = 1;
 }
 
 void DDSHeader::setTexture3D()
@@ -568,6 +644,7 @@ void DDSHeader::setTexture3D()
        this->caps.caps2 = DDSCAPS2_VOLUME;
 
        this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D;
+       this->header10.arraySize = 1;
 }
 
 void DDSHeader::setTextureCube()
@@ -599,21 +676,32 @@ void DDSHeader::setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3)
        this->pf.flags = DDPF_FOURCC;
        this->pf.fourcc = MAKEFOURCC(c0, c1, c2, c3);
 
-       if (this->pf.fourcc == FOURCC_ATI2)
-       {
-               this->pf.bitcount = FOURCC_A2XY;
-       }
-       else
-       {
-               this->pf.bitcount = 0;
-       }
+       this->pf.bitcount = 0;
+       this->pf.rmask = 0;
+       this->pf.gmask = 0;
+       this->pf.bmask = 0;
+       this->pf.amask = 0;
+}
+
+void DDSHeader::setFormatCode(uint32 code)
+{
+       // set fourcc pixel format.
+       this->pf.flags = DDPF_FOURCC;
+       this->pf.fourcc = code;
        
+       this->pf.bitcount = 0;
        this->pf.rmask = 0;
        this->pf.gmask = 0;
        this->pf.bmask = 0;
        this->pf.amask = 0;
 }
 
+void DDSHeader::setSwizzleCode(uint8 c0, uint8 c1, uint8 c2, uint8 c3)
+{
+       this->pf.bitcount = MAKEFOURCC(c0, c1, c2, c3);
+}
+
+
 void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
 {
        // Make sure the masks are correct.
@@ -627,10 +715,24 @@ void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask
                return;
        }
 
-       this->pf.flags = DDPF_RGB;
-
-       if (amask != 0) {
-               this->pf.flags |= DDPF_ALPHAPIXELS;
+       if (rmask != 0 || gmask != 0 || bmask != 0)
+       {
+        if (gmask == 0 && bmask == 0)
+        {
+            this->pf.flags = DDPF_LUMINANCE;
+        }
+        else
+        {
+                   this->pf.flags = DDPF_RGB;
+        }
+
+               if (amask != 0) {
+                       this->pf.flags |= DDPF_ALPHAPIXELS;
+               }
+       }
+       else if (amask != 0)
+       {
+               this->pf.flags |= DDPF_ALPHA;
        }
 
        if (bitcount == 0)
@@ -643,18 +745,16 @@ void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask
                }
        }
 
+    // D3DX functions do not like this:
+       this->pf.fourcc = 0; //findD3D9Format(bitcount, rmask, gmask, bmask, amask);
+    /*if (this->pf.fourcc) {
+        this->pf.flags |= DDPF_FOURCC;
+    }*/
+
        if (!(bitcount > 0 && bitcount <= 32)) {
                printf("DDS: bad bit count, pixel format not set\n");
                return;
        }
-
-       // Align to 8.
-       if (bitcount <= 8) bitcount = 8;
-       else if (bitcount <= 16) bitcount = 16;
-       else if (bitcount <= 24) bitcount = 24;
-       else bitcount = 32;
-
-       this->pf.fourcc = 0; //findD3D9Format(bitcount, rmask, gmask, bmask, amask);
        this->pf.bitcount = bitcount;
        this->pf.rmask = rmask;
        this->pf.gmask = gmask;
@@ -675,10 +775,108 @@ void DDSHeader::setNormalFlag(bool b)
        else this->pf.flags &= ~DDPF_NORMAL;
 }
 
+void DDSHeader::setSrgbFlag(bool b)
+{
+    if (b) this->pf.flags |= DDPF_SRGB;
+    else this->pf.flags &= ~DDPF_SRGB;
+}
+
+void DDSHeader::setHasAlphaFlag(bool b)
+{
+       if (b) this->pf.flags |= DDPF_ALPHAPIXELS;
+       else this->pf.flags &= ~DDPF_ALPHAPIXELS;
+}
+
+void DDSHeader::setUserVersion(int version)
+{
+    this->reserved[7] = FOURCC_UVER;
+    this->reserved[8] = version;
+}
+
+/*
+void DDSHeader::swapBytes()
+{
+       this->fourcc = POSH_LittleU32(this->fourcc);
+       this->size = POSH_LittleU32(this->size);
+       this->flags = POSH_LittleU32(this->flags);
+       this->height = POSH_LittleU32(this->height);
+       this->width = POSH_LittleU32(this->width);
+       this->pitch = POSH_LittleU32(this->pitch);
+       this->depth = POSH_LittleU32(this->depth);
+       this->mipmapcount = POSH_LittleU32(this->mipmapcount);
+       
+       for(int i = 0; i < 11; i++) {
+               this->reserved[i] = POSH_LittleU32(this->reserved[i]);
+       }
+
+       this->pf.size = POSH_LittleU32(this->pf.size);
+       this->pf.flags = POSH_LittleU32(this->pf.flags);
+       this->pf.fourcc = POSH_LittleU32(this->pf.fourcc);
+       this->pf.bitcount = POSH_LittleU32(this->pf.bitcount);
+       this->pf.rmask = POSH_LittleU32(this->pf.rmask);
+       this->pf.gmask = POSH_LittleU32(this->pf.gmask);
+       this->pf.bmask = POSH_LittleU32(this->pf.bmask);
+       this->pf.amask = POSH_LittleU32(this->pf.amask);
+       this->caps.caps1 = POSH_LittleU32(this->caps.caps1);
+       this->caps.caps2 = POSH_LittleU32(this->caps.caps2);
+       this->caps.caps3 = POSH_LittleU32(this->caps.caps3);
+       this->caps.caps4 = POSH_LittleU32(this->caps.caps4);
+       this->notused = POSH_LittleU32(this->notused);
+
+       this->header10.dxgiFormat = POSH_LittleU32(this->header10.dxgiFormat);
+       this->header10.resourceDimension = POSH_LittleU32(this->header10.resourceDimension);
+       this->header10.miscFlag = POSH_LittleU32(this->header10.miscFlag);
+       this->header10.arraySize = POSH_LittleU32(this->header10.arraySize);
+       this->header10.reserved = POSH_LittleU32(this->header10.reserved);
+}
+*/
+
 bool DDSHeader::hasDX10Header() const
 {
-       return this->pf.fourcc == FOURCC_DX10;  // @@ This is according to AMD
-       //return this->pf.flags == 0;             // @@ This is according to MS
+       return this->pf.fourcc == FOURCC_DX10;
+}
+
+uint DDSHeader::signature() const
+{
+    return this->reserved[9];
+}
+
+uint DDSHeader::toolVersion() const
+{
+    return this->reserved[10];
+}
+
+uint DDSHeader::userVersion() const
+{
+    if (this->reserved[7] == FOURCC_UVER) {
+        return this->reserved[8];
+    }
+    return 0;
+}
+
+bool DDSHeader::isNormalMap() const
+{
+    return (pf.flags & DDPF_NORMAL) != 0;
+}
+
+bool DDSHeader::isSrgb() const
+{
+    return (pf.flags & DDPF_SRGB) != 0;
+}
+
+bool DDSHeader::hasAlpha() const
+{
+    return (pf.flags & DDPF_ALPHAPIXELS) != 0;
+}
+
+uint DDSHeader::d3d9Format() const
+{
+    if (pf.flags & DDPF_FOURCC) {
+        return pf.fourcc;
+    }
+    else {
+        return findD3D9Format(pf.bitcount, pf.rmask, pf.gmask, pf.bmask, pf.amask);
+    }
 }
 
 DirectDrawSurface::DirectDrawSurface(unsigned char *mem, uint size) : stream(mem, size), header()
@@ -725,6 +923,16 @@ bool DirectDrawSurface::isSupported() const
 {
        if (header.hasDX10Header())
        {
+               if (header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM ||
+                       header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM ||
+                       header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM ||
+                       header.header10.dxgiFormat == DXGI_FORMAT_BC4_UNORM ||
+                       header.header10.dxgiFormat == DXGI_FORMAT_BC5_UNORM)
+               {
+                       return true;
+               }
+
+               return false;
        }
        else
        {
@@ -743,9 +951,9 @@ bool DirectDrawSurface::isSupported() const
                                return false;
                        }
                }
-               else if (header.pf.flags & DDPF_RGB)
-               {
-                       // All RGB formats are supported now.
+        else if ((header.pf.flags & DDPF_RGB) || (header.pf.flags & DDPF_LUMINANCE))
+        {
+            // All RGB and luminance formats are supported now.
                }
                else
                {
@@ -768,6 +976,41 @@ bool DirectDrawSurface::isSupported() const
        return true;
 }
 
+bool DirectDrawSurface::hasAlpha() const
+{
+       if (header.hasDX10Header())
+       {
+#pragma NV_MESSAGE("TODO: Update hasAlpha to handle all DX10 formats.")
+               return 
+                       header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM ||
+                       header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM ||
+                       header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM;
+       }
+       else
+       {
+               if (header.pf.flags & DDPF_RGB) 
+               {
+                       return header.pf.amask != 0;
+               }
+               else if (header.pf.flags & DDPF_FOURCC)
+               {
+                       if (header.pf.fourcc == FOURCC_RXGB ||
+                               header.pf.fourcc == FOURCC_ATI1 ||
+                               header.pf.fourcc == FOURCC_ATI2 ||
+                               header.pf.flags & DDPF_NORMAL)
+                       {
+                               return false;
+                       }
+                       else
+                       {
+                // @@ Here we could check the ALPHA_PIXELS flag, but nobody sets it. (except us?)
+                               return true;
+                       }
+               }
+
+               return false;
+       }
+}
 
 uint DirectDrawSurface::mipmapCount() const
 {
@@ -794,22 +1037,6 @@ uint DirectDrawSurface::depth() const
        else return 1;
 }
 
-bool DirectDrawSurface::hasAlpha() const
-{
-       if ((header.pf.flags & DDPF_RGB) && (header.pf.amask == 0))
-       {
-               return false;
-       }
-       else if (header.pf.fourcc == FOURCC_DXT1)
-       {
-               return false;
-       }
-       else
-       {
-               return true;
-       }
-}
-
 bool DirectDrawSurface::isTexture1D() const
 {
        if (header.hasDX10Header())
@@ -853,6 +1080,16 @@ void DirectDrawSurface::setNormalFlag(bool b)
        header.setNormalFlag(b);
 }
 
+void DirectDrawSurface::setHasAlphaFlag(bool b)
+{
+       header.setHasAlphaFlag(b);
+}
+
+void DirectDrawSurface::setUserVersion(int version)
+{
+    header.setUserVersion(version);
+}
+
 void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap)
 {
        stream.seek(offset(face, mipmap));
@@ -869,14 +1106,31 @@ void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap)
        
        img->allocate(w, h);
        
-       if (header.pf.flags & DDPF_RGB) 
+       if (hasAlpha())
+       {
+               img->setFormat(Image::Format_ARGB);
+       }
+       else
        {
-               readLinearImage(img);
+               img->setFormat(Image::Format_RGB);
        }
-       else if (header.pf.flags & DDPF_FOURCC)
+
+       if (header.hasDX10Header())
        {
+               // So far only block formats supported.
                readBlockImage(img);
        }
+       else
+       {
+               if (header.pf.flags & DDPF_RGB) 
+               {
+                       readLinearImage(img);
+               }
+               else if (header.pf.flags & DDPF_FOURCC)
+               {
+                       readBlockImage(img);
+               }
+       }
 }
 
 void DirectDrawSurface::readLinearImage(Image * img)
@@ -906,17 +1160,6 @@ void DirectDrawSurface::readLinearImage(Image * img)
                return;
        }
 
-       // set image format: RGB or ARGB
-       // alpha channel exists if and only if the alpha mask is non-zero
-       if (header.pf.amask == 0)
-       {
-               img->setFormat(Image::Format_RGB);
-       }
-       else
-       {
-               img->setFormat(Image::Format_ARGB);
-       }
-
        // Read linear RGB images.
        for (uint y = 0; y < h; y++)
        {
@@ -926,10 +1169,10 @@ void DirectDrawSurface::readLinearImage(Image * img)
                        mem_read(stream, (unsigned char *)(&c), byteCount);
 
                        Color32 pixel(0, 0, 0, 0xFF);
-                       pixel.r = PixelFormat::convert(c >> rshift, rsize, 8);
-                       pixel.g = PixelFormat::convert(c >> gshift, gsize, 8);
-                       pixel.b = PixelFormat::convert(c >> bshift, bsize, 8);
-                       pixel.a = PixelFormat::convert(c >> ashift, asize, 8);
+                       pixel.r = PixelFormat::convert((c & header.pf.rmask) >> rshift, rsize, 8);
+                       pixel.g = PixelFormat::convert((c & header.pf.gmask) >> gshift, gsize, 8);
+                       pixel.b = PixelFormat::convert((c & header.pf.bmask) >> bshift, bsize, 8);
+                       pixel.a = PixelFormat::convert((c & header.pf.amask) >> ashift, asize, 8);
 
                        img->pixel(x, y) = pixel;
                }
@@ -939,19 +1182,6 @@ void DirectDrawSurface::readLinearImage(Image * img)
 void DirectDrawSurface::readBlockImage(Image * img)
 {
 
-       // set image format: RGB or ARGB
-       if (header.pf.fourcc == FOURCC_RXGB ||
-               header.pf.fourcc == FOURCC_ATI1 ||
-               header.pf.fourcc == FOURCC_ATI2 ||
-               header.pf.flags & DDPF_NORMAL)
-       {
-               img->setFormat(Image::Format_RGB);
-       }
-       else
-       {
-               img->setFormat(Image::Format_ARGB);
-       }
-
        const uint w = img->width();
        const uint h = img->height();
        
@@ -993,20 +1223,33 @@ static Color32 buildNormal(uint8 x, uint8 y)
 
 void DirectDrawSurface::readBlock(ColorBlock * rgba)
 {
-       if (header.pf.fourcc == FOURCC_DXT1)
+       uint fourcc = header.pf.fourcc;
+
+       // Map DX10 block formats to fourcc codes.
+       if (header.hasDX10Header())
+       {
+               if (header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM) fourcc = FOURCC_DXT1;
+               if (header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM) fourcc = FOURCC_DXT3;
+               if (header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM) fourcc = FOURCC_DXT5;
+               if (header.header10.dxgiFormat == DXGI_FORMAT_BC4_UNORM) fourcc = FOURCC_ATI1;
+               if (header.header10.dxgiFormat == DXGI_FORMAT_BC5_UNORM) fourcc = FOURCC_ATI2;
+       }
+
+
+       if (fourcc == FOURCC_DXT1)
        {
                BlockDXT1 block;
                mem_read(stream, block);
                block.decodeBlock(rgba);
        }
-       else if (header.pf.fourcc == FOURCC_DXT2 ||
+       else if (fourcc == FOURCC_DXT2 ||
            header.pf.fourcc == FOURCC_DXT3)
        {
                BlockDXT3 block;
                mem_read(stream, block);
                block.decodeBlock(rgba);
        }
-       else if (header.pf.fourcc == FOURCC_DXT4 ||
+       else if (fourcc == FOURCC_DXT4 ||
            header.pf.fourcc == FOURCC_DXT5 ||
            header.pf.fourcc == FOURCC_RXGB)
        {
@@ -1014,7 +1257,7 @@ void DirectDrawSurface::readBlock(ColorBlock * rgba)
                mem_read(stream, block);
                block.decodeBlock(rgba);
                
-               if (header.pf.fourcc == FOURCC_RXGB)
+               if (fourcc == FOURCC_RXGB)
                {
                        // Swap R & A.
                        for (int i = 0; i < 16; i++)
@@ -1026,13 +1269,13 @@ void DirectDrawSurface::readBlock(ColorBlock * rgba)
                        }
                }
        }
-       else if (header.pf.fourcc == FOURCC_ATI1)
+       else if (fourcc == FOURCC_ATI1)
        {
                BlockATI1 block;
                mem_read(stream, block);
                block.decodeBlock(rgba);
        }
-       else if (header.pf.fourcc == FOURCC_ATI2)
+       else if (fourcc == FOURCC_ATI2)
        {
                BlockATI2 block;
                mem_read(stream, block);
@@ -1042,7 +1285,7 @@ void DirectDrawSurface::readBlock(ColorBlock * rgba)
        // If normal flag set, convert to normal.
        if (header.pf.flags & DDPF_NORMAL)
        {
-               if (header.pf.fourcc == FOURCC_ATI2)
+               if (fourcc == FOURCC_ATI2)
                {
                        for (int i = 0; i < 16; i++)
                        {
@@ -1050,7 +1293,7 @@ void DirectDrawSurface::readBlock(ColorBlock * rgba)
                                c = buildNormal(c.r, c.g);
                        }
                }
-               else if (header.pf.fourcc == FOURCC_DXT5)
+               else if (fourcc == FOURCC_DXT5)
                {
                        for (int i = 0; i < 16; i++)
                        {
@@ -1076,6 +1319,27 @@ uint DirectDrawSurface::blockSize() const
                case FOURCC_RXGB:
                case FOURCC_ATI2:
                        return 16;
+               case FOURCC_DX10:
+                       switch(header.header10.dxgiFormat)
+                       {
+                               case DXGI_FORMAT_BC1_TYPELESS:
+                               case DXGI_FORMAT_BC1_UNORM:
+                               case DXGI_FORMAT_BC1_UNORM_SRGB:
+                               case DXGI_FORMAT_BC4_TYPELESS:
+                               case DXGI_FORMAT_BC4_UNORM:
+                               case DXGI_FORMAT_BC4_SNORM:
+                                       return 8;
+                               case DXGI_FORMAT_BC2_TYPELESS:
+                               case DXGI_FORMAT_BC2_UNORM:
+                               case DXGI_FORMAT_BC2_UNORM_SRGB:
+                               case DXGI_FORMAT_BC3_TYPELESS:
+                               case DXGI_FORMAT_BC3_UNORM:
+                               case DXGI_FORMAT_BC3_UNORM_SRGB:
+                               case DXGI_FORMAT_BC5_TYPELESS:
+                               case DXGI_FORMAT_BC5_UNORM:
+                               case DXGI_FORMAT_BC5_SNORM:
+                                       return 16;
+                       };
        };
 
        // Not a block image.
@@ -1102,14 +1366,10 @@ uint DirectDrawSurface::mipmapSize(uint mipmap) const
                h = (h + 3) / 4;
                return blockSize() * w * h;
        }
-       else if (header.pf.flags & DDPF_RGB)
+       else if (header.pf.flags & DDPF_RGB || (header.pf.flags & DDPF_LUMINANCE))
        {
-               // Align pixels to bytes.
-               uint byteCount = (header.pf.bitcount + 7) / 8;
-               
-               // Align pitch to 4 bytes.
-               uint pitch = 4 * ((w * byteCount + 3) / 4);
-               
+        uint pitch = computePitch(w, header.pf.bitcount, 8); // Asuming 8 bit alignment, which is the same D3DX expects.
+       
                return pitch * h * d;
        }
        else {
@@ -1133,7 +1393,7 @@ uint DirectDrawSurface::faceSize() const
 
 uint DirectDrawSurface::offset(const uint face, const uint mipmap)
 {
-       uint size = 128; //sizeof(DDSHeader);
+       uint size = 128; // sizeof(DDSHeader);
        
        if (header.hasDX10Header())
        {
@@ -1156,7 +1416,6 @@ uint DirectDrawSurface::offset(const uint face, const uint mipmap)
 
 void DirectDrawSurface::printInfo() const
 {
-       /* 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]); */
        printf("Flags: 0x%.8X\n", header.flags);
        if (header.flags & DDSD_CAPS) printf("\tDDSD_CAPS\n");
        if (header.flags & DDSD_PIXELFORMAT) printf("\tDDSD_PIXELFORMAT\n");
@@ -1175,9 +1434,9 @@ void DirectDrawSurface::printInfo() const
        printf("Mipmap count: %d\n", header.mipmapcount);
        
        printf("Pixel Format:\n");
-       /* printf("\tSize: %d\n", header.pf.size); */
        printf("\tFlags: 0x%.8X\n", header.pf.flags);
        if (header.pf.flags & DDPF_RGB) printf("\t\tDDPF_RGB\n");
+    if (header.pf.flags & DDPF_LUMINANCE) printf("\t\tDDPF_LUMINANCE\n");
        if (header.pf.flags & DDPF_FOURCC) printf("\t\tDDPF_FOURCC\n");
        if (header.pf.flags & DDPF_ALPHAPIXELS) printf("\t\tDDPF_ALPHAPIXELS\n");
        if (header.pf.flags & DDPF_ALPHA) printf("\t\tDDPF_ALPHA\n");
@@ -1188,23 +1447,30 @@ void DirectDrawSurface::printInfo() const
        if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n");
        if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n");
        
-       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));
-       if ((header.pf.fourcc & DDPF_FOURCC) && (header.pf.bitcount != 0))
+    if (header.pf.fourcc != 0) { 
+        // Display fourcc code even when DDPF_FOURCC flag not set.
+        printf("\tFourCC: '%c%c%c%c' (0x%.8X)\n",
+                       ((header.pf.fourcc >> 0) & 0xFF),
+                       ((header.pf.fourcc >> 8) & 0xFF),
+                       ((header.pf.fourcc >> 16) & 0xFF),
+            ((header.pf.fourcc >> 24) & 0xFF), 
+            header.pf.fourcc);
+    }
+
+    if ((header.pf.flags & DDPF_FOURCC) && (header.pf.bitcount != 0))
        {
-               printf("\tSwizzle: '%c%c%c%c'\n", 
+        printf("\tSwizzle: '%c%c%c%c' (0x%.8X)\n", 
                        (header.pf.bitcount >> 0) & 0xFF,
                        (header.pf.bitcount >> 8) & 0xFF,
                        (header.pf.bitcount >> 16) & 0xFF,
-                       (header.pf.bitcount >> 24) & 0xFF);
+            (header.pf.bitcount >> 24) & 0xFF,
+            header.pf.bitcount);
        }
        else
        {
                printf("\tBit count: %d\n", header.pf.bitcount);
        }
+
        printf("\tRed mask: 0x%.8X\n", header.pf.rmask);
        printf("\tGreen mask: 0x%.8X\n", header.pf.gmask);
        printf("\tBlue mask: 0x%.8X\n", header.pf.bmask);
@@ -1244,7 +1510,7 @@ void DirectDrawSurface::printInfo() const
                printf("\tArray size: %u\n", header.header10.arraySize);
        }
        
-       if (header.reserved[9] == MAKEFOURCC('N', 'V', 'T', 'T'))
+    if (header.reserved[9] == FOURCC_NVTT)
        {
                int major = (header.reserved[10] >> 16) & 0xFF;
                int minor = (header.reserved[10] >> 8) & 0xFF;
@@ -1253,5 +1519,10 @@ void DirectDrawSurface::printInfo() const
                printf("Version:\n");
                printf("\tNVIDIA Texture Tools %d.%d.%d\n", major, minor, revision);
        }
+
+    if (header.reserved[7] == FOURCC_UVER)
+    {
+        printf("User Version: %d\n", header.reserved[8]);
+    }
 }