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). --- .../blender/imbuf/intern/dds/DirectDrawSurface.cpp | 487 ++++++++++++++++----- 1 file changed, 379 insertions(+), 108 deletions(-) (limited to 'source/blender/imbuf/intern/dds/DirectDrawSurface.cpp') 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]); + } } -- cgit v1.2.3