From 1cdcea316421f49a8d2dc712e89ff5b5fd1035d1 Mon Sep 17 00:00:00 2001 From: castano Date: Tue, 17 Jul 2007 09:16:28 +0000 Subject: [PATCH] Add support for arbitrary rgb pixel formats. --- src/nvimage/DirectDrawSurface.cpp | 69 +++++++++++++++++- src/nvimage/nvtt/CompressRGB.cpp | 114 ++++++++++++++++-------------- 2 files changed, 128 insertions(+), 55 deletions(-) diff --git a/src/nvimage/DirectDrawSurface.cpp b/src/nvimage/DirectDrawSurface.cpp index 098b17b..39f6555 100644 --- a/src/nvimage/DirectDrawSurface.cpp +++ b/src/nvimage/DirectDrawSurface.cpp @@ -53,7 +53,7 @@ namespace static const uint FOURCC_ATI1 = MAKEFOURCC('A', 'T', 'I', '1'); static const uint FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2'); - // RGB formats. + // 32 bit RGB formats. static const uint D3DFMT_R8G8B8 = 20; static const uint D3DFMT_A8R8G8B8 = 21; static const uint D3DFMT_X8R8G8B8 = 22; @@ -70,6 +70,7 @@ namespace static const uint D3DFMT_X8B8G8R8 = 33; static const uint D3DFMT_G16R16 = 34; static const uint D3DFMT_A2R10G10B10 = 35; + static const uint D3DFMT_A16B16G16R16 = 36; // Palette formats. @@ -80,6 +81,7 @@ namespace static const uint D3DFMT_L8 = 50; static const uint D3DFMT_A8L8 = 51; static const uint D3DFMT_A4L4 = 52; + static const uint D3DFMT_L16 = 81; // Floating point formats static const uint D3DFMT_R16F = 111; @@ -167,8 +169,62 @@ namespace nv s << header.notused; return s; } + + struct FormatDescriptor + { + uint format; + uint bitcount; + uint rmask; + uint gmask; + uint bmask; + uint amask; + }; + + 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_L8, 8, 8, 0, 0, 0 }, // DXGI_FORMAT_R8_UNORM + { D3DFMT_L16, 16, 16, 0, 0, 0 }, // DXGI_FORMAT_R16_UNORM + }; + + const uint s_d3dFormatCount = sizeof(s_d3dFormats) / sizeof(s_d3dFormats[0]); + + static uint findD3DFormat(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() { this->fourcc = FOURCC_DDS; @@ -307,10 +363,17 @@ void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask bitcount++; total >>= 1; } - // @@ Align to 8? } - this->pf.fourcc = 0; + nvCheck(bitcount > 0 && bitcount <= 32); + + // 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 = findD3DFormat(bitcount, rmask, gmask, bmask, amask); this->pf.bitcount = bitcount; this->pf.rmask = rmask; this->pf.gmask = gmask; diff --git a/src/nvimage/nvtt/CompressRGB.cpp b/src/nvimage/nvtt/CompressRGB.cpp index 3e9f2bb..b01a1d0 100644 --- a/src/nvimage/nvtt/CompressRGB.cpp +++ b/src/nvimage/nvtt/CompressRGB.cpp @@ -21,9 +21,10 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. -#include #include + #include +#include #include "CompressRGB.h" #include "CompressionOptions.h" @@ -43,42 +44,41 @@ namespace return ((p + 3) / 4) * 4; } - static void convert_to_rgba8888(void * src, void * dst, uint w) - { - // @@ TODO - } - - static void convert_to_bgra8888(const void * src, void * dst, uint w) + static void convert_to_a8r8g8b8(const void * src, void * dst, uint w) { memcpy(dst, src, 4 * w); } - static void convert_to_rgb888(const void * src, void * dst, uint w) + static void convert_to_x8r8g8b8(const void * src, void * dst, uint w) { - // @@ TODO + memcpy(dst, src, 4 * w); } - static uint truncate(uint c, uint inbits, uint outbits) + static uint convert(uint c, uint inbits, uint outbits) { - nvDebugCheck(inbits > outbits); - c >>= inbits - outbits; + if (inbits <= outbits) + { + // truncate + return c >> (inbits - outbits); + } + else + { + // bitexpand + return (c << (outbits - inbits)) | convert(c, inbits, outbits - inbits); + } } - static uint bitexpand(uint c, uint inbits, uint outbits) + static void maskShiftAndSize(uint mask, uint * shift, uint * size) { - // @@ TODO - } - - static void maskShiftAndSize(uint mask, uint & shift, uint & size) - { - shift = 0; + *shift = 0; while((mask & 1) == 0) { - shift++; + *shift++; mask >>= 1; } + *size = 0; while((mask & 1) == 1) { - size++; + *size++; mask >>= 1; } } @@ -94,52 +94,63 @@ void nv::compressRGB(const Image * image, const OutputOptions & outputOptions, c const uint w = image->width(); const uint h = image->height(); - uint rshift, rsize; - maskShiftAndSize(compressionOptions.rmask, rshift, rsize); - - uint gshift, gsize; - maskShiftAndSize(compressionOptions.gmask, gshift, gsize); - - uint bshift, bsize; - maskShiftAndSize(compressionOptions.bmask, bshift, bsize); - - uint ashift, asize; - maskShiftAndSize(compressionOptions.amask, ashift, asize); + const uint bitCount = compressionOptions.bitcount; + nvCheck(bitCount == 8 || bitCount == 16 || bitCount == 24 || bitCount == 32); + const uint byteCount = bitCount / 8; + + const uint rmask = compressionOptions.rmask; + uint rshift, rsize; + maskShiftAndSize(rmask, &rshift, &rsize); + + const uint gmask = compressionOptions.gmask; + uint gshift, gsize; + maskShiftAndSize(gmask, &gshift, &gsize); + + const uint bmask = compressionOptions.bmask; + uint bshift, bsize; + maskShiftAndSize(bmask, &bshift, &bsize); + + const uint amask = compressionOptions.amask; + uint ashift, asize; + maskShiftAndSize(amask, &ashift, &asize); + + // @@ Perform error diffusion dithering. // Determine pitch. uint pitch = computePitch(w, compressionOptions.bitcount); - void * dst = malloc(pitch); + void * dst = mem::malloc(pitch); for (uint y = 0; y < h; y++) { const Color32 * src = image->scanline(y); - convert_to_bgra8888(src, dst, w); - - if (false) + if (bitCount == 32 && rmask == 0xFF0000 && gmask == 0xFF00 && bmask == 0xFF && amask == 0xFF000000) { - // uint c = 0; - // c |= (src[i].r >> (8 - rsize)) << rshift; - // c |= (src[i].g >> (8 - gsize)) << gshift; - // c |= (src[i].b >> (8 - bsize)) << bshift; + convert_to_a8r8g8b8(src, dst, w); } - - /* - if (rmask == 0xFF000000 && gmask == 0xFF0000 && bmask == 0xFF00 && amask == 0xFF) + else if (bitCount == 32 && rmask == 0xFF0000 && gmask == 0xFF00 && bmask == 0xFF && amask == 0) { - convert_to_rgba8888(src, dst, w); - } - else if (rmask == 0xFF0000 && gmask == 0xFF00 && bmask == 0xFF && amask == 0) - { - convert_to_rgb888(src, dst, w); + convert_to_x8r8g8b8(src, dst, w); } else { - // @@ Not supported. + // Generic pixel format conversion. + for (uint x = 0; x < w; x++) + { + uint c = 0; + c |= convert(src[x].r, 8, rsize) << rshift; + c |= convert(src[x].g, 8, gsize) << gshift; + c |= convert(src[x].b, 8, bsize) << bshift; + c |= convert(src[x].a, 8, asize) << ashift; + + *(uint *)dst = c; + + ++src; + dst = (uint8 *)dst + byteCount; + } } - */ if (outputOptions.outputHandler != NULL) { @@ -147,7 +158,6 @@ void nv::compressRGB(const Image * image, const OutputOptions & outputOptions, c } } - free(dst); + mem::free(dst); } -