From 96655b3e7cc0f3fc0314431d8b2f8b1cca6a33db Mon Sep 17 00:00:00 2001 From: castano Date: Sat, 26 Jul 2008 10:03:12 +0000 Subject: [PATCH] Work in progress: - better support for DDS10 file format. - support for RGBA pixel formats with more than 32 bits. - support for pixel types other than UNORM. --- src/nvimage/DirectDrawSurface.cpp | 21 +++ src/nvtt/CompressionOptions.h | 2 + src/nvtt/Compressor.cpp | 212 ++++++++++++++++++++---------- src/nvtt/OutputOptions.cpp | 7 + src/nvtt/OutputOptions.h | 1 + src/nvtt/nvtt.h | 33 +++++ 6 files changed, 207 insertions(+), 69 deletions(-) diff --git a/src/nvimage/DirectDrawSurface.cpp b/src/nvimage/DirectDrawSurface.cpp index f7667e6..72b5587 100644 --- a/src/nvimage/DirectDrawSurface.cpp +++ b/src/nvimage/DirectDrawSurface.cpp @@ -1144,6 +1144,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. diff --git a/src/nvtt/CompressionOptions.h b/src/nvtt/CompressionOptions.h index 0a30673..3508ff3 100644 --- a/src/nvtt/CompressionOptions.h +++ b/src/nvtt/CompressionOptions.h @@ -46,6 +46,8 @@ namespace nvtt uint bmask; uint amask; + PixelType pixelType; + nv::String externalCompressor; // Quantization. diff --git a/src/nvtt/Compressor.cpp b/src/nvtt/Compressor.cpp index be7de90..59afd76 100644 --- a/src/nvtt/Compressor.cpp +++ b/src/nvtt/Compressor.cpp @@ -323,80 +323,154 @@ bool Compressor::Private::outputHeader(const InputOptions::Private & inputOption return true; } - DDSHeader header; - - header.setWidth(inputOptions.targetWidth); - header.setHeight(inputOptions.targetHeight); - - int mipmapCount = inputOptions.realMipmapCount(); - nvDebugCheck(mipmapCount > 0); - - header.setMipmapCount(mipmapCount); - - if (inputOptions.textureType == TextureType_2D) { - header.setTexture2D(); - } - else if (inputOptions.textureType == TextureType_Cube) { - header.setTextureCube(); - } - /*else if (inputOptions.textureType == TextureType_3D) { - header.setTexture3D(); - header.setDepth(inputOptions.targetDepth); - }*/ - - if (compressionOptions.format == Format_RGBA) + if (outputOptions.container == Container_DDS || outputOptions.container == Container_DDS10) { - header.setPitch(computePitch(inputOptions.targetWidth, compressionOptions.bitcount)); - header.setPixelFormat(compressionOptions.bitcount, compressionOptions.rmask, compressionOptions.gmask, compressionOptions.bmask, compressionOptions.amask); - } - else - { - header.setLinearSize(computeImageSize(inputOptions.targetWidth, inputOptions.targetHeight, inputOptions.targetDepth, compressionOptions.bitcount, compressionOptions.format)); + DDSHeader header; + + header.setWidth(inputOptions.targetWidth); + header.setHeight(inputOptions.targetHeight); - if (compressionOptions.format == Format_DXT1 || compressionOptions.format == Format_DXT1a || compressionOptions.format == Format_DXT1n) { - header.setFourCC('D', 'X', 'T', '1'); - if (inputOptions.isNormalMap) header.setNormalFlag(true); - } - else if (compressionOptions.format == Format_DXT3) { - header.setFourCC('D', 'X', 'T', '3'); - } - else if (compressionOptions.format == Format_DXT5) { - header.setFourCC('D', 'X', 'T', '5'); - } - else if (compressionOptions.format == Format_DXT5n) { - header.setFourCC('D', 'X', 'T', '5'); - if (inputOptions.isNormalMap) header.setNormalFlag(true); - } - else if (compressionOptions.format == Format_BC4) { - header.setFourCC('A', 'T', 'I', '1'); - } - else if (compressionOptions.format == Format_BC5) { - header.setFourCC('A', 'T', 'I', '2'); - if (inputOptions.isNormalMap) header.setNormalFlag(true); - } - else if (compressionOptions.format == Format_CTX1) { - header.setFourCC('C', 'T', 'X', '1'); - if (inputOptions.isNormalMap) header.setNormalFlag(true); - } - } - - // Swap bytes if necessary. - header.swapBytes(); - - uint headerSize = 128; - if (header.hasDX10Header()) - { - nvStaticCheck(sizeof(DDSHeader) == 128 + 20); - headerSize = 128 + 20; - } + int mipmapCount = inputOptions.realMipmapCount(); + nvDebugCheck(mipmapCount > 0); + + header.setMipmapCount(mipmapCount); - bool writeSucceed = outputOptions.outputHandler->writeData(&header, headerSize); - if (!writeSucceed && outputOptions.errorHandler != NULL) - { - outputOptions.errorHandler->error(Error_FileWrite); + bool supported = true; + + if (outputOptions.container == Container_DDS10) + { + if (compressionOptions.format == Format_RGBA) + { + if (compressionOptions.bitcount == 16) + { + // B5G6R5_UNORM + // B5G5R5A1_UNORM + supported = false; + } + else if (compressionOptions.bitcount == 32) + { + // B8G8R8A8_UNORM + // B8G8R8X8_UNORM + // R8G8B8A8_UNORM + // R10G10B10A2_UNORM + supported = false; + } + else { + supported = false; + } + } + else + { + if (compressionOptions.format == Format_DXT1 || compressionOptions.format == Format_DXT1a || compressionOptions.format == Format_DXT1n) { + header.setDX10Format(71); + if (inputOptions.isNormalMap) header.setNormalFlag(true); + } + else if (compressionOptions.format == Format_DXT3) { + header.setDX10Format(74); + } + else if (compressionOptions.format == Format_DXT5) { + header.setDX10Format(77); + } + else if (compressionOptions.format == Format_DXT5n) { + header.setDX10Format(77); + if (inputOptions.isNormalMap) header.setNormalFlag(true); + } + else if (compressionOptions.format == Format_BC4) { + header.setDX10Format(80); + } + else if (compressionOptions.format == Format_BC5) { + header.setDX10Format(83); + if (inputOptions.isNormalMap) header.setNormalFlag(true); + } + else { + supported = false; + } + } + } + else + { + if (compressionOptions.format == Format_RGBA) + { + header.setPitch(computePitch(inputOptions.targetWidth, compressionOptions.bitcount)); + header.setPixelFormat(compressionOptions.bitcount, compressionOptions.rmask, compressionOptions.gmask, compressionOptions.bmask, compressionOptions.amask); + } + else + { + header.setLinearSize(computeImageSize(inputOptions.targetWidth, inputOptions.targetHeight, inputOptions.targetDepth, compressionOptions.bitcount, compressionOptions.format)); + + if (compressionOptions.format == Format_DXT1 || compressionOptions.format == Format_DXT1a || compressionOptions.format == Format_DXT1n) { + header.setFourCC('D', 'X', 'T', '1'); + if (inputOptions.isNormalMap) header.setNormalFlag(true); + } + else if (compressionOptions.format == Format_DXT3) { + header.setFourCC('D', 'X', 'T', '3'); + } + else if (compressionOptions.format == Format_DXT5) { + header.setFourCC('D', 'X', 'T', '5'); + } + else if (compressionOptions.format == Format_DXT5n) { + header.setFourCC('D', 'X', 'T', '5'); + if (inputOptions.isNormalMap) header.setNormalFlag(true); + } + else if (compressionOptions.format == Format_BC4) { + header.setFourCC('A', 'T', 'I', '1'); + } + else if (compressionOptions.format == Format_BC5) { + header.setFourCC('A', 'T', 'I', '2'); + if (inputOptions.isNormalMap) header.setNormalFlag(true); + } + else if (compressionOptions.format == Format_CTX1) { + header.setFourCC('C', 'T', 'X', '1'); + if (inputOptions.isNormalMap) header.setNormalFlag(true); + } + else { + supported = false; + } + } + } + + if (!supported) + { + // This container does not support the requested format. + if (outputOptions.errorHandler != NULL) + { + outputOptions.errorHandler->error(Error_UnsupportedFeature); + } + + return false; + } + + if (inputOptions.textureType == TextureType_2D) { + header.setTexture2D(); + } + else if (inputOptions.textureType == TextureType_Cube) { + header.setTextureCube(); + } + /*else if (inputOptions.textureType == TextureType_3D) { + header.setTexture3D(); + header.setDepth(inputOptions.targetDepth); + }*/ + + // Swap bytes if necessary. + header.swapBytes(); + + uint headerSize = 128; + if (header.hasDX10Header()) + { + nvStaticCheck(sizeof(DDSHeader) == 128 + 20); + headerSize = 128 + 20; + } + + bool writeSucceed = outputOptions.outputHandler->writeData(&header, headerSize); + if (!writeSucceed && outputOptions.errorHandler != NULL) + { + outputOptions.errorHandler->error(Error_FileWrite); + } + + return writeSucceed; } - return writeSucceed; + return true; } diff --git a/src/nvtt/OutputOptions.cpp b/src/nvtt/OutputOptions.cpp index 7cf8420..a307330 100644 --- a/src/nvtt/OutputOptions.cpp +++ b/src/nvtt/OutputOptions.cpp @@ -43,6 +43,7 @@ void OutputOptions::reset() m.outputHandler = NULL; m.errorHandler = NULL; m.outputHeader = true; + m.container = Container_DDS; } @@ -72,6 +73,12 @@ void OutputOptions::setOutputHeader(bool outputHeader) m.outputHeader = outputHeader; } +/// Set container. +void OutputOptions::setContainer(Container container) +{ + m.container = container; +} + bool OutputOptions::Private::openFile() const { diff --git a/src/nvtt/OutputOptions.h b/src/nvtt/OutputOptions.h index bddc28f..8118c8d 100644 --- a/src/nvtt/OutputOptions.h +++ b/src/nvtt/OutputOptions.h @@ -64,6 +64,7 @@ namespace nvtt mutable OutputHandler * outputHandler; ErrorHandler * errorHandler; bool outputHeader; + Container container; bool openFile() const; void closeFile() const; diff --git a/src/nvtt/nvtt.h b/src/nvtt/nvtt.h index 3cfcd35..1bf67b8 100644 --- a/src/nvtt/nvtt.h +++ b/src/nvtt/nvtt.h @@ -87,6 +87,16 @@ namespace nvtt Format_DXT1n, Format_CTX1, }; + + /// Pixel types. + enum PixelType + { + PixelType_UnsignedNorm, + PixelType_SignedNorm, + PixelType_UnsignedInt, + PixelType_SignedInt, + PixelType_Float, + }; /// Quality modes. enum Quality @@ -115,10 +125,25 @@ namespace nvtt // Set color mask to describe the RGB/RGBA format. NVTT_API void setPixelFormat(unsigned int bitcount, unsigned int rmask, unsigned int gmask, unsigned int bmask, unsigned int amask); + + // As + NVTT_API void setPixelFormat2(unsigned int rsize, unsigned int gsize, unsigned int bsize, unsigned int asize); + + NVTT_API void setPixelType(PixelType pixelType); NVTT_API void setQuantization(bool colorDithering, bool alphaDithering, bool binaryAlpha, int alphaThreshold = 127); }; + /* + // DXGI_FORMAT_R16G16_FLOAT + compressionOptions.setPixelType(PixelType_Float); + compressionOptions.setPixelFormat2(16, 16, 0, 0); + + // DXGI_FORMAT_R32G32B32A32_FLOAT + compressionOptions.setPixelType(PixelType_Float); + compressionOptions.setPixelFormat2(32, 32, 32, 32); + */ + /// Wrap modes. enum WrapMode @@ -267,6 +292,13 @@ namespace nvtt virtual void error(Error e) = 0; }; + /// Container. + enum Container + { + Container_DDS, + Container_DDS10, + }; + /// Output Options. This class holds pointers to the interfaces that are used to report the output of /// the compressor to the user. @@ -285,6 +317,7 @@ namespace nvtt NVTT_API void setOutputHandler(OutputHandler * outputHandler); NVTT_API void setErrorHandler(ErrorHandler * errorHandler); NVTT_API void setOutputHeader(bool outputHeader); + NVTT_API void setContainer(Container container); };