From ed3fd722108ea4d41167c8339a97ecd818e78cdf Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Sun, 8 May 2011 09:05:52 +0000 Subject: Apply second half of [#21590] .dds textures: fix for DXT1n format + sync with upstream nvtt submitted by Amorilia This updates the DDS module with upstearm nvtt (r1042). --- source/blender/imbuf/intern/dds/BlockDXT.cpp | 77 ++++ source/blender/imbuf/intern/dds/BlockDXT.h | 6 +- source/blender/imbuf/intern/dds/ColorBlock.cpp | 186 ++++++-- source/blender/imbuf/intern/dds/ColorBlock.h | 19 +- source/blender/imbuf/intern/dds/Common.h | 6 + .../blender/imbuf/intern/dds/DirectDrawSurface.cpp | 487 ++++++++++++++++----- .../blender/imbuf/intern/dds/DirectDrawSurface.h | 20 +- source/blender/imbuf/intern/dds/Image.cpp | 5 +- source/blender/imbuf/intern/dds/PixelFormat.h | 32 ++ 9 files changed, 667 insertions(+), 171 deletions(-) (limited to 'source/blender/imbuf') diff --git a/source/blender/imbuf/intern/dds/BlockDXT.cpp b/source/blender/imbuf/intern/dds/BlockDXT.cpp index b634a4d938e..0d17f16532b 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.cpp +++ b/source/blender/imbuf/intern/dds/BlockDXT.cpp @@ -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. diff --git a/source/blender/imbuf/intern/dds/BlockDXT.h b/source/blender/imbuf/intern/dds/BlockDXT.h index 6e9e555d963..aa0c1c509ca 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.h +++ b/source/blender/imbuf/intern/dds/BlockDXT.h @@ -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(); diff --git a/source/blender/imbuf/intern/dds/ColorBlock.cpp b/source/blender/imbuf/intern/dds/ColorBlock.cpp index 3dcfa0cef43..edb69934231 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.cpp +++ b/source/blender/imbuf/intern/dds/ColorBlock.cpp @@ -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(); } +*/ + diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h index 47b08303a05..d4e4e8a809f 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.h +++ b/source/blender/imbuf/intern/dds/ColorBlock.h @@ -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; diff --git a/source/blender/imbuf/intern/dds/Common.h b/source/blender/imbuf/intern/dds/Common.h index 9cf1de3644a..a6dcf69febf 100644 --- a/source/blender/imbuf/intern/dds/Common.h +++ b/source/blender/imbuf/intern/dds/Common.h @@ -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 diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp index b179432da4a..ceac1d2ae18 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -69,12 +69,11 @@ #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]); + } } diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h index 4db621be3da..5978e780991 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.h +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h @@ -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); diff --git a/source/blender/imbuf/intern/dds/Image.cpp b/source/blender/imbuf/intern/dds/Image.cpp index 9c34c4e7199..b9ec1c0c3aa 100644 --- a/source/blender/imbuf/intern/dds/Image.cpp +++ b/source/blender/imbuf/intern/dds/Image.cpp @@ -41,7 +41,7 @@ #include // 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; } + diff --git a/source/blender/imbuf/intern/dds/PixelFormat.h b/source/blender/imbuf/intern/dds/PixelFormat.h index 2602681d979..35c6eacb972 100644 --- a/source/blender/imbuf/intern/dds/PixelFormat.h +++ b/source/blender/imbuf/intern/dds/PixelFormat.h @@ -107,6 +107,38 @@ } } + 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 -- cgit v1.2.3