Apply second half of [#21590] .dds textures: fix for DXT1n format + sync with upstrea...
authorNathan Letwory <nathan@letworyinteractive.com>
Sun, 8 May 2011 09:05:52 +0000 (09:05 +0000)
committerNathan Letwory <nathan@letworyinteractive.com>
Sun, 8 May 2011 09:05:52 +0000 (09:05 +0000)
submitted by Amorilia

This updates the DDS module with upstearm nvtt (r1042).

source/blender/imbuf/intern/dds/BlockDXT.cpp
source/blender/imbuf/intern/dds/BlockDXT.h
source/blender/imbuf/intern/dds/ColorBlock.cpp
source/blender/imbuf/intern/dds/ColorBlock.h
source/blender/imbuf/intern/dds/Common.h
source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
source/blender/imbuf/intern/dds/DirectDrawSurface.h
source/blender/imbuf/intern/dds/Image.cpp
source/blender/imbuf/intern/dds/PixelFormat.h

index b634a4d938ebc7bcb965ec5b3a7f411a94978d1a..0d17f16532b689e39c9f4e6acfa99c5e2771b6fa 100644 (file)
@@ -123,6 +123,53 @@ uint BlockDXT1::evaluatePalette(Color32 color_array[4]) const
        }
 }
 
+
+uint BlockDXT1::evaluatePaletteNV5x(Color32 color_array[4]) const
+{
+       // Does bit expansion before interpolation.
+       color_array[0].b = (3 * col0.b * 22) / 8;
+       color_array[0].g = (col0.g << 2) | (col0.g >> 4);
+       color_array[0].r = (3 * col0.r * 22) / 8;
+       color_array[0].a = 0xFF;
+
+       color_array[1].r = (3 * col1.r * 22) / 8;
+       color_array[1].g = (col1.g << 2) | (col1.g >> 4);
+       color_array[1].b = (3 * col1.b * 22) / 8;
+       color_array[1].a = 0xFF;
+       
+    int gdiff = color_array[1].g - color_array[0].g;
+
+       if( col0.u > col1.u ) {
+               // Four-color block: derive the other two colors.
+        color_array[2].r = ((2 * col0.r + col1.r) * 22) / 8;
+        color_array[2].g = (256 * color_array[0].g + gdiff / 4 + 128 + gdiff * 80) / 256;
+        color_array[2].b = ((2 * col0.b + col1.b) * 22) / 8;
+               color_array[2].a = 0xFF;
+               
+        color_array[3].r = ((2 * col1.r + col0.r) * 22) / 8;
+        color_array[3].g = (256 * color_array[1].g - gdiff / 4 + 128 - gdiff * 80) / 256;
+        color_array[3].b = ((2 * col1.b + col0.b) * 22) / 8;
+               color_array[3].a = 0xFF;
+
+               return 4;
+       }
+       else {
+               // Three-color block: derive the other color.
+        color_array[2].r = ((col0.r + col1.r) * 33) / 8;
+        color_array[2].g = (256 * color_array[0].g + gdiff / 4 + 128 + gdiff * 128) / 256;
+        color_array[2].b = ((col0.b + col1.b) * 33) / 8;
+               color_array[2].a = 0xFF;
+               
+               // Set all components to 0 to match DXT specs.
+               color_array[3].r = 0x00; // color_array[2].r;
+               color_array[3].g = 0x00; // color_array[2].g;
+               color_array[3].b = 0x00; // color_array[2].b;
+               color_array[3].a = 0x00;
+               
+               return 3;
+       }
+}
+
 // Evaluate palette assuming 3 color block.
 void BlockDXT1::evaluatePalette3(Color32 color_array[4]) const
 {
@@ -174,6 +221,7 @@ void BlockDXT1::evaluatePalette4(Color32 color_array[4]) const
        color_array[3].a = 0xFF;
 }
 
+
 void BlockDXT1::decodeBlock(ColorBlock * block) const
 {
        // Decode color block.
@@ -189,6 +237,21 @@ void BlockDXT1::decodeBlock(ColorBlock * block) const
        }       
 }
 
+void BlockDXT1::decodeBlockNV5x(ColorBlock * block) const
+{
+       // Decode color block.
+       Color32 color_array[4];
+       evaluatePaletteNV5x(color_array);
+
+       // Write color block.
+       for( uint j = 0; j < 4; j++ ) {
+               for( uint i = 0; i < 4; i++ ) {
+                       uint idx = (row[j] >> (2 * i)) & 3;
+                       block->color(i, j) = color_array[idx];
+               }
+       }
+}
+
 void BlockDXT1::setIndices(int * idx)
 {
        indices = 0;
@@ -225,6 +288,12 @@ void BlockDXT3::decodeBlock(ColorBlock * block) const
        alpha.decodeBlock(block);
 }
 
+void BlockDXT3::decodeBlockNV5x(ColorBlock * block) const
+{
+       color.decodeBlockNV5x(block);
+       alpha.decodeBlock(block);
+}
+
 void AlphaBlockDXT3::decodeBlock(ColorBlock * block) const
 {
        block->color(0x0).a = (alpha0 << 4) | alpha0;
@@ -394,7 +463,15 @@ void BlockDXT5::decodeBlock(ColorBlock * block) const
        
        // Decode alpha.
        alpha.decodeBlock(block);
+}
 
+void BlockDXT5::decodeBlockNV5x(ColorBlock * block) const
+{
+       // Decode color.
+       color.decodeBlockNV5x(block);
+       
+       // Decode alpha.
+       alpha.decodeBlock(block);
 }
 
 /// Flip DXT5 block vertically.
index 6e9e555d96344bcf48113dc6f9d30428e10a1397..aa0c1c509ca111090e91d067f9f2eba4e9545df5 100644 (file)
@@ -78,11 +78,13 @@ struct BlockDXT1
        bool isFourColorMode() const;
 
        uint evaluatePalette(Color32 color_array[4]) const;
-       uint evaluatePaletteFast(Color32 color_array[4]) const;
+       uint evaluatePaletteNV5x(Color32 color_array[4]) const;
+
        void evaluatePalette3(Color32 color_array[4]) const;
        void evaluatePalette4(Color32 color_array[4]) const;
        
        void decodeBlock(ColorBlock * block) const;
+       void decodeBlockNV5x(ColorBlock * block) const;
        
        void setIndices(int * idx);
 
@@ -136,6 +138,7 @@ struct BlockDXT3
        BlockDXT1 color;
        
        void decodeBlock(ColorBlock * block) const;
+       void decodeBlockNV5x(ColorBlock * block) const;
        
        void flip4();
        void flip2();
@@ -213,6 +216,7 @@ struct BlockDXT5
        BlockDXT1 color;
        
        void decodeBlock(ColorBlock * block) const;
+       void decodeBlockNV5x(ColorBlock * block) const;
        
        void flip4();
        void flip2();
index 3dcfa0cef43b34271ad276f29cd1d0d0f5869c66..edb699342310f98ed7bdda9208ca076f71a7a52b 100644 (file)
@@ -83,65 +83,90 @@ ColorBlock::ColorBlock(const Image * img, uint x, uint y)
 
 void ColorBlock::init(const Image * img, uint x, uint y)
 {
-       const uint bw = min(img->width() - x, 4U);
-       const uint bh = min(img->height() - y, 4U);
+    init(img->width(), img->height(), (const uint *)img->pixels(), x, y);
+}
 
-       static int remainder[] = {
-               0, 0, 0, 0,
-               0, 1, 0, 1,
-               0, 1, 2, 0,
-               0, 1, 2, 3,
-       };
+void ColorBlock::init(uint w, uint h, const uint * data, uint x, uint y)
+{
+       const uint bw = min(w - x, 4U);
+       const uint bh = min(h - y, 4U);
 
-       // Blocks that are smaller than 4x4 are handled by repeating the pixels.
-       // @@ Thats only correct when block size is 1, 2 or 4, but not with 3. :(
+    // Blocks that are smaller than 4x4 are handled by repeating the pixels.
+    // @@ Thats only correct when block size is 1, 2 or 4, but not with 3. :(
+    // @@ Ideally we should zero the weights of the pixels out of range.
 
-       for(uint i = 0; i < 4; i++) {
-               //const int by = i % bh;
-               const int by = remainder[(bh - 1) * 4 + i];
-               for(uint e = 0; e < 4; e++) {
-                       //const int bx = e % bw;
-                       const int bx = remainder[(bw - 1) * 4 + e];
-                       color(e, i) = img->pixel(x + bx, y + by);
-               }
-       }
-}
+    for (uint i = 0; i < 4; i++)
+    {
+        const int by = i % bh;
+
+        for (uint e = 0; e < 4; e++)
+        {
+            const int bx = e % bw;
+            const uint idx = (y + by) * w + x + bx;
 
+            color(e, i).u = data[idx];
+        }
+    }
+}
 
-void ColorBlock::swizzleDXT5n()
+void ColorBlock::init(uint w, uint h, const float * data, uint x, uint y)
 {
-       for(int i = 0; i < 16; i++)
+    const uint bw = min(w - x, 4U);
+    const uint bh = min(h - y, 4U);
+
+       // Blocks that are smaller than 4x4 are handled by repeating the pixels.
+       // @@ Thats only correct when block size is 1, 2 or 4, but not with 3. :(
+    // @@ Ideally we should zero the weights of the pixels out of range.
+
+    uint srcPlane = w * h;
+
+       for (uint i = 0; i < 4; i++)
        {
-               Color32 c = m_color[i];
-               m_color[i] = Color32(0xFF, c.g, 0, c.r);
+               const uint by = i % bh;
+               
+               for (uint e = 0; e < 4; e++)
+               {
+                       const uint bx = e % bw;
+            const uint idx = ((y + by) * w + x + bx);
+                       
+                       Color32 & c = color(e, i);
+            c.r = uint8(255 * clamp(data[idx + 0 * srcPlane], 0.0f, 1.0f)); // @@ Is this the right way to quantize floats to bytes?
+            c.g = uint8(255 * clamp(data[idx + 1 * srcPlane], 0.0f, 1.0f));
+            c.b = uint8(255 * clamp(data[idx + 2 * srcPlane], 0.0f, 1.0f));
+            c.a = uint8(255 * clamp(data[idx + 3 * srcPlane], 0.0f, 1.0f));
+               }
        }
 }
 
-void ColorBlock::splatX()
+static inline uint8 component(Color32 c, uint i)
 {
-       for(int i = 0; i < 16; i++)
-       {
-               uint8 x = m_color[i].r;
-               m_color[i] = Color32(x, x, x, x);
-       }
+       if (i == 0) return c.r;
+       if (i == 1) return c.g;
+       if (i == 2) return c.b;
+       if (i == 3) return c.a;
+       if (i == 4) return 0xFF;
+       return 0;
 }
 
-void ColorBlock::splatY()
+void ColorBlock::swizzle(uint x, uint y, uint z, uint w)
 {
-       for(int i = 0; i < 16; i++)
+       for (int i = 0; i < 16; i++)
        {
-               uint8 y = m_color[i].g;
-               m_color[i] = Color32(y, y, y, y);
+               Color32 c = m_color[i];
+               m_color[i].r = component(c, x);
+               m_color[i].g = component(c, y);
+               m_color[i].b = component(c, z);
+               m_color[i].a = component(c, w);
        }
 }
 
+
 /// Returns true if the block has a single color.
-bool ColorBlock::isSingleColor() const
+bool ColorBlock::isSingleColor(Color32 mask/*= Color32(0xFF, 0xFF, 0xFF, 0x00)*/) const
 {
-       Color32 mask(0xFF, 0xFF, 0xFF, 0x00);
        uint u = m_color[0].u & mask.u;
        
-       for(int i = 1; i < 16; i++)
+       for (int i = 1; i < 16; i++)
        {
                if (u != (m_color[i].u & mask.u))
                {
@@ -152,6 +177,7 @@ bool ColorBlock::isSingleColor() const
        return true;
 }
 
+/*
 /// Returns true if the block has a single color, ignoring transparent pixels.
 bool ColorBlock::isSingleColorNoAlpha() const
 {
@@ -159,7 +185,7 @@ bool ColorBlock::isSingleColorNoAlpha() const
        int i;
        for(i = 0; i < 16; i++)
        {
-               if (m_color[i].a != 0) c = m_color[i];
+        if (m_color[i].a != 0) c = m_color[i];
        }
 
        Color32 mask(0xFF, 0xFF, 0xFF, 0x00);
@@ -175,9 +201,10 @@ bool ColorBlock::isSingleColorNoAlpha() const
        
        return true;
 }
+*/
 
 /// Count number of unique colors in this color block.
-uint ColorBlock::countUniqueColors() const
+/*uint ColorBlock::countUniqueColors() const
 {
        uint count = 0;
 
@@ -197,9 +224,9 @@ uint ColorBlock::countUniqueColors() const
        }
        
        return count;
-}
+}*/
 
-/// Get average color of the block.
+/*/// Get average color of the block.
 Color32 ColorBlock::averageColor() const
 {
        uint r, g, b, a;
@@ -213,7 +240,7 @@ Color32 ColorBlock::averageColor() const
        }
        
        return Color32(uint8(r / 16), uint8(g / 16), uint8(b / 16), uint8(a / 16));
-}
+}*/
 
 /// Return true if the block is not fully opaque.
 bool ColorBlock::hasAlpha() const
@@ -225,6 +252,7 @@ bool ColorBlock::hasAlpha() const
        return false;
 }
 
+#if 0
 
 /// Get diameter color range.
 void ColorBlock::diameterRange(Color32 * start, Color32 * end) const
@@ -345,8 +373,9 @@ void ColorBlock::boundsRangeAlpha(Color32 * start, Color32 * end) const
        *start = minColor;
        *end = maxColor;
 }
+#endif
 
-/// Sort colors by abosolute value in their 16 bit representation.
+/*/// Sort colors by abosolute value in their 16 bit representation.
 void ColorBlock::sortColorsByAbsoluteValue()
 {
        // Dummy selection sort.
@@ -364,4 +393,75 @@ void ColorBlock::sortColorsByAbsoluteValue()
                }
                swap( m_color[a], m_color[max] );
        }
+}*/
+
+
+/*/// Find extreme colors in the given axis.
+void ColorBlock::computeRange(Vector3::Arg axis, Color32 * start, Color32 * end) const
+{
+       
+       int mini, maxi;
+       mini = maxi = 0;
+       
+       float min, max; 
+       min = max = dot(Vector3(m_color[0].r, m_color[0].g, m_color[0].b), axis);
+
+       for(uint i = 1; i < 16; i++)
+       {
+               const Vector3 vec(m_color[i].r, m_color[i].g, m_color[i].b);
+               
+               float val = dot(vec, axis);
+               if( val < min ) {
+                       mini = i;
+                       min = val;
+               }
+               else if( val > max ) {
+                       maxi = i;
+                       max = val;
+               }
+       }
+       
+       *start = m_color[mini];
+       *end = m_color[maxi];
+}*/
+
+
+/*/// Sort colors in the given axis.
+void ColorBlock::sortColors(const Vector3 & axis)
+{
+       float luma_array[16];
+       
+       for(uint i = 0; i < 16; i++) {
+               const Vector3 vec(m_color[i].r, m_color[i].g, m_color[i].b);
+               luma_array[i] = dot(vec, axis);
+       }
+       
+       // Dummy selection sort.
+       for( uint a = 0; a < 16; a++ ) {
+               uint min = a;
+               for( uint b = a+1; b < 16; b++ ) {
+                       if( luma_array[b] < luma_array[min] ) {
+                               min = b;
+                       }
+               }
+               swap( luma_array[a], luma_array[min] );
+               swap( m_color[a], m_color[min] );
+       }
+}*/
+
+
+/*/// Get the volume of the color block.
+float ColorBlock::volume() const
+{
+       Box bounds;
+       bounds.clearBounds();
+       
+       for(int i = 0; i < 16; i++) {
+               const Vector3 point(m_color[i].r, m_color[i].g, m_color[i].b);
+               bounds.addPointToBounds(point);
+       }
+       
+       return bounds.volume();
 }
+*/
+
index 47b08303a0528a5abcb5f7de5cc7c22429dc91ab..d4e4e8a809ffd89c3a57a8fb366be7503ec6f853 100644 (file)
@@ -51,26 +51,15 @@ struct ColorBlock
        ColorBlock(const Image * img, uint x, uint y);
        
        void init(const Image * img, uint x, uint y);
+    void init(uint w, uint h, const uint * data, uint x, uint y);
+    void init(uint w, uint h, const float * data, uint x, uint y);
        
-       void swizzleDXT5n();
-       void splatX();
-       void splatY();
+       void swizzle(uint x, uint y, uint z, uint w); // 0=r, 1=g, 2=b, 3=a, 4=0xFF, 5=0
        
-       bool isSingleColor() const;
-       bool isSingleColorNoAlpha() const;
-       uint countUniqueColors() const;
-       Color32 averageColor() const;
+    bool isSingleColor(Color32 mask = Color32(0xFF, 0xFF, 0xFF, 0x00)) const;
        bool hasAlpha() const;
        
-       void diameterRange(Color32 * start, Color32 * end) const;
-       void luminanceRange(Color32 * start, Color32 * end) const;
-       void boundsRange(Color32 * start, Color32 * end) const;
-       void boundsRangeAlpha(Color32 * start, Color32 * end) const;
        
-       void sortColorsByAbsoluteValue();
-
-       float volume() const;
-
        // Accessors
        const Color32 * colors() const;
 
index 9cf1de3644a7eb706fcbcfa7f3175e7620be4f36..a6dcf69febf755dc6c0e9f799e3428441b5aeffe 100644 (file)
@@ -55,4 +55,10 @@ typedef unsigned int       uint;
 typedef unsigned int       uint32;
 typedef unsigned long long uint64;
 
+// copied from nvtt src/nvimage/nvimage.h
+inline uint computePitch(uint w, uint bitsize, uint alignment)
+{
+       return ((w * bitsize +  8 * alignment - 1) / (8 * alignment)) * alignment;
+}
+
 #endif
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]);
+    }
 }
 
index 4db621be3da7f4bcfb742f199c2f4427dbd336d7..5978e780991abe95765fa32aee84872a602b9772 100644 (file)
@@ -126,11 +126,25 @@ struct DDSHeader
        void setLinearSize(uint size);
        void setPitch(uint pitch);
        void setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3);
+       void setFormatCode(uint code);
+       void setSwizzleCode(uint8 c0, uint8 c1, uint8 c2, uint8 c3);
        void setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask);
        void setDX10Format(uint format);
        void setNormalFlag(bool b);
+    void setSrgbFlag(bool b);
+       void setHasAlphaFlag(bool b);
+        void setUserVersion(int version);
+       
+       /*void swapBytes();*/
        
        bool hasDX10Header() const;
+    uint signature() const;
+    uint toolVersion() const;
+    uint userVersion() const;
+    bool isNormalMap() const;
+    bool isSrgb() const;
+    bool hasAlpha() const;
+    uint d3d9Format() const;
 };
 
 /// DirectDraw Surface. (DDS)
@@ -142,6 +156,8 @@ public:
        
        bool isValid() const;
        bool isSupported() const;
+
+       bool hasAlpha() const;
        
        uint mipmapCount() const;
        uint width() const;
@@ -153,8 +169,8 @@ public:
        bool isTextureCube() const;
 
        void setNormalFlag(bool b);
-
-       bool hasAlpha() const; /* false for DXT1, true for all other DXTs */
+       void setHasAlphaFlag(bool b);
+        void setUserVersion(int version);
        
        void mipmap(Image * img, uint f, uint m);
        //      void mipmap(FloatImage * img, uint f, uint m);
index 9c34c4e71997449ef7370a26677c24fb72cb5ee3..b9ec1c0c3aa194c8d6f520b4c72257e9ece33cc4 100644 (file)
@@ -41,7 +41,7 @@
 
 #include <stdio.h> // printf
 
-Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(0)
+Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(NULL)
 {
 }
 
@@ -61,7 +61,7 @@ void Image::allocate(uint w, uint h)
 void Image::free()
 {
        if (m_data) delete [] m_data;
-       m_data = 0;
+       m_data = NULL;
 }
 
 
@@ -132,3 +132,4 @@ void Image::setFormat(Image::Format f)
        m_format = f;
 }
 
+
index 2602681d979c83fe954ac7d41f1431a6e746e981..35c6eacb9722709948024d260aef60275bc6a89d 100644 (file)
                        }
                }
 
+        inline float quantizeCeil(float f, int inbits, int outbits)
+        {
+            //uint i = f * (float(1 << inbits) - 1);
+            //i = convert(i, inbits, outbits);
+            //float result = float(i) / (float(1 << outbits) - 1);
+            //nvCheck(result >= f);
+            float result;
+            int offset = 0;
+            do {
+                uint i = offset + uint(f * (float(1 << inbits) - 1));
+                i = convert(i, inbits, outbits);
+                result = float(i) / (float(1 << outbits) - 1);
+                offset++;
+            } while (result < f);
+
+            return result;
+        }
+
+        /*
+        inline float quantizeRound(float f, int bits)
+        {
+            float scale = float(1 << bits);
+            return fround(f * scale) / scale;
+        }
+
+        inline float quantizeFloor(float f, int bits)
+        {
+            float scale = float(1 << bits);
+            return floor(f * scale) / scale;
+        }
+        */
+
        } // PixelFormat namespace
 
 #endif // _DDS_IMAGE_PIXELFORMAT_H