diff --git a/src/nvimage/ImageIO.cpp b/src/nvimage/ImageIO.cpp index d15cb5c..d28b270 100644 --- a/src/nvimage/ImageIO.cpp +++ b/src/nvimage/ImageIO.cpp @@ -6,6 +6,7 @@ #include "TgaFile.h" #include "PsdFile.h" #include "DirectDrawSurface.h" +#include "PixelFormat.h" #include "nvmath/Color.h" #include "nvmath/Half.h" @@ -290,7 +291,7 @@ bool nv::ImageIO::saveFloat(const char * fileName, Stream & s, const FloatImage image->setFormat(Image::Format_ARGB); } - return ImageIO::save(fileName, image.ptr()); + return ImageIO::save(fileName, s, image.ptr()); } #endif // defined(HAVE_FREEIMAGE) @@ -299,9 +300,9 @@ bool nv::ImageIO::saveFloat(const char * fileName, Stream & s, const FloatImage bool nv::ImageIO::saveFloat(const char * fileName, const FloatImage * fimage, uint baseComponent, uint componentCount) { -#if !defined(HAVE_FREEIMAGE) const char * extension = Path::extension(fileName); +#if !defined(HAVE_FREEIMAGE) #if defined(HAVE_OPENEXR) if (strCaseCmp(extension, ".exr") == 0) { return saveFloatEXR(fileName, fimage, baseComponent, componentCount); @@ -312,16 +313,15 @@ bool nv::ImageIO::saveFloat(const char * fileName, const FloatImage * fimage, ui return saveFloatTIFF(fileName, fimage, baseComponent, componentCount); } #endif - #endif // !defined(HAVE_FREEIMAGE) - StdInputStream stream(fileName); + StdOutputStream stream(fileName); - if (stream.isError()) { - return false; - } + if (stream.isError()) { + return false; + } - return saveFloat(fileName, stream, fimage, baseComponent, componentCount); + return saveFloat(fileName, stream, fimage, baseComponent, componentCount); } #if defined(HAVE_FREEIMAGE) @@ -448,6 +448,38 @@ FloatImage * nv::ImageIO::loadFloatFreeImage(FREE_IMAGE_FORMAT fif, Stream & s) switch (fit) { + case FIT_BITMAP: + { + floatImage->allocate(4, w, h); + FIBITMAP * tmp = FreeImage_ConvertTo32Bits(bitmap); + + uint bitcount = FreeImage_GetBPP(bitmap); + uint byteCount = bitcount / 8; + + for (int y=0; y < h; y++) + { + const Color32 * src = (const Color32 *)FreeImage_GetScanLine(bitmap, h - y - 1 ); + + float * r = floatImage->scanline(y, 0); + float * g = floatImage->scanline(y, 1); + float * b = floatImage->scanline(y, 2); + float * a = floatImage->scanline(y, 3); + + for (int x=0; x < w; x++) + { + r[x] = float(src[x].r) / 255.0f; + g[x] = float(src[x].g) / 255.0f; + b[x] = float(src[x].b) / 255.0f; + a[x] = float(src[x].a) / 255.0f; + } + + src += byteCount; + } + + FreeImage_Unload(tmp); + } + + break; case FIT_FLOAT: floatImage->allocate(1, w, h); @@ -1216,7 +1248,7 @@ bool nv::ImageIO::savePNG(Stream & s, const Image * img, const ImageMetaData * t png_set_write_fn(png_ptr, (void*)&s, user_write_data, user_write_flush); // Set image header information - int color_type = PNG_COLOR_TYPE_RGB; + int color_type = PNG_COLOR_TYPE_RGBA; switch(img->format()) { case Image::Format_RGB: color_type = PNG_COLOR_TYPE_RGB; break; @@ -1231,6 +1263,7 @@ bool nv::ImageIO::savePNG(Stream & s, const Image * img, const ImageMetaData * t png_bytep * row_data = new png_bytep[sizeof(png_byte) * img->height()]; for (uint i = 0; i < img->height(); i++) { row_data[i] = (png_byte*)img->scanline (i); + if (img->format() == Image::Format_RGB) row_data[i]--; // This is a bit of a hack, libpng expects images in ARGB format not BGRA, it supports BGR swapping, but not alpha swapping. } png_set_rows(png_ptr, info_ptr, row_data); @@ -1252,9 +1285,10 @@ bool nv::ImageIO::savePNG(Stream & s, const Image * img, const ImageMetaData * t png_write_png(png_ptr, info_ptr, // component order is BGR(A) - PNG_TRANSFORM_BGR + PNG_TRANSFORM_BGR | // Strip alpha byte for RGB images - | (img->format() == Image::Format_RGB ? PNG_TRANSFORM_STRIP_FILLER : 0), + (img->format() == Image::Format_RGB ? PNG_TRANSFORM_STRIP_FILLER : 0) + , NULL); // Finish things up diff --git a/src/nvtt/CompressionOptions.cpp b/src/nvtt/CompressionOptions.cpp index 53e41a5..e24ef55 100644 --- a/src/nvtt/CompressionOptions.cpp +++ b/src/nvtt/CompressionOptions.cpp @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/CompressionOptions.h b/src/nvtt/CompressionOptions.h index 08420c6..7c2d658 100644 --- a/src/nvtt/CompressionOptions.h +++ b/src/nvtt/CompressionOptions.h @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/Compressor.h b/src/nvtt/Compressor.h index 0e7f82d..ed10160 100644 --- a/src/nvtt/Compressor.h +++ b/src/nvtt/Compressor.h @@ -1,4 +1,5 @@ -// Copyright Ignacio Castano 2009 +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/CompressorDX10.cpp b/src/nvtt/CompressorDX10.cpp index 5345f75..550a978 100644 --- a/src/nvtt/CompressorDX10.cpp +++ b/src/nvtt/CompressorDX10.cpp @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/CompressorDX10.h b/src/nvtt/CompressorDX10.h index 382190b..355e642 100644 --- a/src/nvtt/CompressorDX10.h +++ b/src/nvtt/CompressorDX10.h @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/CompressorDX11.cpp b/src/nvtt/CompressorDX11.cpp index 4b61dfb..d698842 100644 --- a/src/nvtt/CompressorDX11.cpp +++ b/src/nvtt/CompressorDX11.cpp @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/CompressorDX11.h b/src/nvtt/CompressorDX11.h index 9aef3a1..0022811 100644 --- a/src/nvtt/CompressorDX11.h +++ b/src/nvtt/CompressorDX11.h @@ -1,4 +1,4 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/CompressorDX9.cpp b/src/nvtt/CompressorDX9.cpp index a514770..5a4eae4 100644 --- a/src/nvtt/CompressorDX9.cpp +++ b/src/nvtt/CompressorDX9.cpp @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/CompressorDX9.h b/src/nvtt/CompressorDX9.h index 8c6c7e7..4e8730d 100644 --- a/src/nvtt/CompressorDX9.h +++ b/src/nvtt/CompressorDX9.h @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/CompressorDXT.cpp b/src/nvtt/CompressorDXT.cpp index b798f76..0bd57f8 100644 --- a/src/nvtt/CompressorDXT.cpp +++ b/src/nvtt/CompressorDXT.cpp @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/CompressorDXT.h b/src/nvtt/CompressorDXT.h index 1f211b3..bdc9f95 100644 --- a/src/nvtt/CompressorDXT.h +++ b/src/nvtt/CompressorDXT.h @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/CompressorRGB.cpp b/src/nvtt/CompressorRGB.cpp index 3330ee3..990a33a 100644 --- a/src/nvtt/CompressorRGB.cpp +++ b/src/nvtt/CompressorRGB.cpp @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/CompressorRGB.h b/src/nvtt/CompressorRGB.h index 75dda52..0ae5a1d 100644 --- a/src/nvtt/CompressorRGB.h +++ b/src/nvtt/CompressorRGB.h @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/CompressorRGBE.cpp b/src/nvtt/CompressorRGBE.cpp index 3cc22b5..4fc4354 100644 --- a/src/nvtt/CompressorRGBE.cpp +++ b/src/nvtt/CompressorRGBE.cpp @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/CompressorRGBE.h b/src/nvtt/CompressorRGBE.h index 6fcedf6..d7c18b7 100644 --- a/src/nvtt/CompressorRGBE.h +++ b/src/nvtt/CompressorRGBE.h @@ -1,4 +1,4 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/Context.cpp b/src/nvtt/Context.cpp index 7628f33..4ecaeb5 100644 --- a/src/nvtt/Context.cpp +++ b/src/nvtt/Context.cpp @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2008 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2008-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -133,9 +134,9 @@ bool Compressor::outputHeader(const TexImage & tex, int mipmapCount, const Compr return m.outputHeader(TextureType_2D, tex.width(), tex.height(), tex.depth(), mipmapCount, tex.isNormalMap(), compressionOptions.m, outputOptions.m); } -bool Compressor::compress(const TexImage & tex, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const +bool Compressor::compress(const TexImage & tex, int face, int mipmap, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const { - return m.compress(tex, compressionOptions.m, outputOptions.m); + return m.compress(tex, face, mipmap, compressionOptions.m, outputOptions.m); } int Compressor::estimateSize(const TexImage & tex, int mipmapCount, const CompressionOptions & compressionOptions) const @@ -149,9 +150,9 @@ int Compressor::estimateSize(const TexImage & tex, int mipmapCount, const Compre // Raw API. -bool Compressor::compress(int w, int h, int d, const float * rgba, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const +bool Compressor::compress(int w, int h, int d, int face, int mipmap, const float * rgba, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const { - return m.compress(AlphaMode_None, w, h, d, rgba, compressionOptions.m, outputOptions.m); + return m.compress(AlphaMode_None, w, h, d, face, mipmap, rgba, compressionOptions.m, outputOptions.m); } int Compressor::estimateSize(int w, int h, int d, int mipmapCount, const CompressionOptions & compressionOptions) const @@ -244,20 +245,14 @@ bool Compressor::Private::compress(const InputOptions::Private & inputOptions, c tmp.toGamma(inputOptions.outputGamma); } - int size = computeImageSize(w, h, d, compressionOptions.bitcount, compressionOptions.pitchAlignment, compressionOptions.format); - outputOptions.beginImage(size, w, h, d, f, 0); - quantize(tmp, compressionOptions); - compress(tmp, compressionOptions, outputOptions); + compress(tmp, f, 0, compressionOptions, outputOptions); for (int m = 1; m < mipmapCount; m++) { w = max(1, w/2); h = max(1, h/2); d = max(1, d/2); - int size = computeImageSize(w, h, d, compressionOptions.bitcount, compressionOptions.pitchAlignment, compressionOptions.format); - outputOptions.beginImage(size, w, h, d, f, m); - int idx = m * faceCount + f; bool useSourceImages = false; @@ -296,24 +291,27 @@ bool Compressor::Private::compress(const InputOptions::Private & inputOptions, c } quantize(tmp, compressionOptions); - compress(tmp, compressionOptions, outputOptions); + compress(tmp, f, m, compressionOptions, outputOptions); } } return true; } -bool Compressor::Private::compress(const TexImage & tex, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const +bool Compressor::Private::compress(const TexImage & tex, int face, int mipmap, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const { - if (!compress(tex.alphaMode(), tex.width(), tex.height(), tex.depth(), tex.data(), compressionOptions, outputOptions)) { + if (!compress(tex.alphaMode(), tex.width(), tex.height(), tex.depth(), face, mipmap, tex.data(), compressionOptions, outputOptions)) { return false; } return true; } -bool Compressor::Private::compress(AlphaMode alphaMode, int w, int h, int d, const float * rgba, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const +bool Compressor::Private::compress(AlphaMode alphaMode, int w, int h, int d, int face, int mipmap, const float * rgba, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const { + int size = computeImageSize(w, h, d, compressionOptions.bitcount, compressionOptions.pitchAlignment, compressionOptions.format); + outputOptions.beginImage(size, w, h, d, face, mipmap); + // Decide what compressor to use. AutoPtr compressor; #if defined HAVE_CUDA @@ -340,7 +338,7 @@ bool Compressor::Private::compress(AlphaMode alphaMode, int w, int h, int d, con } -bool Compressor::Private::quantize(TexImage & img, const CompressionOptions::Private & compressionOptions) const +void Compressor::Private::quantize(TexImage & img, const CompressionOptions::Private & compressionOptions) const { if (compressionOptions.enableColorDithering) { if (compressionOptions.format >= Format_BC1 && compressionOptions.format <= Format_BC3) { @@ -362,7 +360,7 @@ bool Compressor::Private::quantize(TexImage & img, const CompressionOptions::Pri } } else if (compressionOptions.binaryAlpha) { - img.binarize(3, compressionOptions.alphaThreshold, compressionOptions.enableAlphaDithering); + img.binarize(3, float(compressionOptions.alphaThreshold)/255.0f, compressionOptions.enableAlphaDithering); } } diff --git a/src/nvtt/Context.h b/src/nvtt/Context.h index a053e77..523ad02 100644 --- a/src/nvtt/Context.h +++ b/src/nvtt/Context.h @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2008 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -43,11 +44,11 @@ namespace nvtt { Private() {} - bool compress(const TexImage & tex, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const; bool compress(const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const; - bool compress(AlphaMode alphaMode, int w, int h, int d, const float * data, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const; + bool compress(const TexImage & tex, int face, int mipmap, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const; + bool compress(AlphaMode alphaMode, int w, int h, int d, int face, int mipmap, const float * data, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const; - bool quantize(TexImage & tex, const CompressionOptions::Private & compressionOptions) const; + void quantize(TexImage & tex, const CompressionOptions::Private & compressionOptions) const; bool outputHeader(nvtt::TextureType textureType, int w, int h, int d, int mipmapCount, bool isNormalMap, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const; //bool outputHeader(const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const; diff --git a/src/nvtt/InputOptions.cpp b/src/nvtt/InputOptions.cpp index d9eeb5a..a0c2159 100644 --- a/src/nvtt/InputOptions.cpp +++ b/src/nvtt/InputOptions.cpp @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -157,7 +158,7 @@ void InputOptions::resetTextureLayout() if (m.images != NULL) { // Delete images. - for (int i = 0; i < m.imageCount; i++) { + for (uint i = 0; i < m.imageCount; i++) { free(m.images[i]); } @@ -178,14 +179,14 @@ bool InputOptions::setMipmapData(const void * data, int width, int height, int d if (depth != 1) { return false; } - if (face >= m.faceCount) { + if (uint(face) >= m.faceCount) { return false; } - if (mipLevel >= m.mipmapCount) { + if (uint(mipLevel) >= m.mipmapCount) { return false; } - const int idx = mipLevel * m.faceCount + face; + const uint idx = mipLevel * m.faceCount + face; if (idx >= m.imageCount) { return false; } diff --git a/src/nvtt/InputOptions.h b/src/nvtt/InputOptions.h index 675e3bd..4a9915e 100644 --- a/src/nvtt/InputOptions.h +++ b/src/nvtt/InputOptions.h @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/OptimalCompressDXT.cpp b/src/nvtt/OptimalCompressDXT.cpp index bc2c24c..df57c85 100644 --- a/src/nvtt/OptimalCompressDXT.cpp +++ b/src/nvtt/OptimalCompressDXT.cpp @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/OptimalCompressDXT.h b/src/nvtt/OptimalCompressDXT.h index 2932e94..5fcd0e1 100644 --- a/src/nvtt/OptimalCompressDXT.h +++ b/src/nvtt/OptimalCompressDXT.h @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2008 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/OutputOptions.cpp b/src/nvtt/OutputOptions.cpp index 1ae7da1..226bfcd 100644 --- a/src/nvtt/OutputOptions.cpp +++ b/src/nvtt/OutputOptions.cpp @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/OutputOptions.h b/src/nvtt/OutputOptions.h index 619ad7c..e021d46 100644 --- a/src/nvtt/OutputOptions.h +++ b/src/nvtt/OutputOptions.h @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/QuickCompressDXT.cpp b/src/nvtt/QuickCompressDXT.cpp index 213463f..5f8e4b8 100644 --- a/src/nvtt/QuickCompressDXT.cpp +++ b/src/nvtt/QuickCompressDXT.cpp @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/QuickCompressDXT.h b/src/nvtt/QuickCompressDXT.h index d5d262d..43d48cb 100644 --- a/src/nvtt/QuickCompressDXT.h +++ b/src/nvtt/QuickCompressDXT.h @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/TexImage.cpp b/src/nvtt/TexImage.cpp index f9594a3..e162b66 100644 --- a/src/nvtt/TexImage.cpp +++ b/src/nvtt/TexImage.cpp @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -472,9 +473,7 @@ bool TexImage::setImage2D(InputFormat format, int w, int h, const void * r, cons bool TexImage::setImage2D(Format format, Decoder decoder, int w, int h, const void * data) { -#pragma NV_MESSAGE("TODO: Add support for all compressed formats in TexImage::setImage2D.") - - if (format != nvtt::Format_BC1 && format != nvtt::Format_BC2 && format != nvtt::Format_BC3) + if (format != nvtt::Format_BC1 && format != nvtt::Format_BC2 && format != nvtt::Format_BC3 && format != nvtt::Format_BC4 && format != nvtt::Format_BC5) { return false; } @@ -500,59 +499,69 @@ bool TexImage::setImage2D(Format format, Decoder decoder, int w, int h, const vo { ColorBlock colors; - if (format == nvtt::Format_BC1) - { - const BlockDXT1 * block = (const BlockDXT1 *)ptr; - - if (decoder == Decoder_Reference) { - block->decodeBlock(&colors); - } - else if (decoder == Decoder_NV5x) { - block->decodeBlockNV5x(&colors); - } - } - else if (format == nvtt::Format_BC2) - { - const BlockDXT3 * block = (const BlockDXT3 *)ptr; - - if (decoder == Decoder_Reference) { - block->decodeBlock(&colors); - } - else if (decoder == Decoder_NV5x) { - block->decodeBlockNV5x(&colors); - } - } - else if (format == nvtt::Format_BC3) - { - const BlockDXT5 * block = (const BlockDXT5 *)ptr; - - if (decoder == Decoder_Reference) { - block->decodeBlock(&colors); - } - else if (decoder == Decoder_NV5x) { - block->decodeBlockNV5x(&colors); - } - } - - for (int yy = 0; yy < 4; yy++) - { - for (int xx = 0; xx < 4; xx++) - { - Color32 c = colors.color(xx, yy); - - if (x * 4 + xx < w && y * 4 + yy < h) - { - m->image->pixel(x*4 + xx, y*4 + yy, 0) = float(c.r) * 1.0f/255.0f; - m->image->pixel(x*4 + xx, y*4 + yy, 1) = float(c.g) * 1.0f/255.0f; - m->image->pixel(x*4 + xx, y*4 + yy, 2) = float(c.b) * 1.0f/255.0f; - m->image->pixel(x*4 + xx, y*4 + yy, 3) = float(c.a) * 1.0f/255.0f; - } - } - } - - ptr += bs; + if (format == nvtt::Format_BC1) + { + const BlockDXT1 * block = (const BlockDXT1 *)ptr; + + if (decoder == Decoder_Reference) { + block->decodeBlock(&colors); + } + else if (decoder == Decoder_NV5x) { + block->decodeBlockNV5x(&colors); + } + } + else if (format == nvtt::Format_BC2) + { + const BlockDXT3 * block = (const BlockDXT3 *)ptr; + + if (decoder == Decoder_Reference) { + block->decodeBlock(&colors); + } + else if (decoder == Decoder_NV5x) { + block->decodeBlockNV5x(&colors); + } + } + else if (format == nvtt::Format_BC3) + { + const BlockDXT5 * block = (const BlockDXT5 *)ptr; + + if (decoder == Decoder_Reference) { + block->decodeBlock(&colors); + } + else if (decoder == Decoder_NV5x) { + block->decodeBlockNV5x(&colors); + } + } + else if (format == nvtt::Format_BC4) + { + const BlockATI1 * block = (const BlockATI1 *)ptr; + block->decodeBlock(&colors); + } + else if (format == nvtt::Format_BC5) + { + const BlockATI2 * block = (const BlockATI2 *)ptr; + block->decodeBlock(&colors); + } + + for (int yy = 0; yy < 4; yy++) + { + for (int xx = 0; xx < 4; xx++) + { + Color32 c = colors.color(xx, yy); + + if (x * 4 + xx < w && y * 4 + yy < h) + { + m->image->pixel(x*4 + xx, y*4 + yy, 0) = float(c.r) * 1.0f/255.0f; + m->image->pixel(x*4 + xx, y*4 + yy, 1) = float(c.g) * 1.0f/255.0f; + m->image->pixel(x*4 + xx, y*4 + yy, 2) = float(c.b) * 1.0f/255.0f; + m->image->pixel(x*4 + xx, y*4 + yy, 3) = float(c.a) * 1.0f/255.0f; + } + } + } + + ptr += bs; + } } - } } catch(...) { return false; @@ -803,6 +812,7 @@ void TexImage::swizzle(int r, int g, int b, int a) m->image->swizzle(0, r, g, b, a); } +// color * scale + bias void TexImage::scaleBias(int channel, float scale, float bias) { if (m->image == NULL) return; @@ -1038,21 +1048,44 @@ void TexImage::toRGBM(float range/*= 1*/, float threshold/*= 0.25*/) const uint count = img->width() * img->height(); for (uint i = 0; i < count; i++) { - float ri = nv::clamp(r[i] * irange, 0.0f, 1.0f); - float gi = nv::clamp(g[i] * irange, 0.0f, 1.0f); - float bi = nv::clamp(b[i] * irange, 0.0f, 1.0f); + float R = nv::clamp(r[i] * irange, 0.0f, 1.0f); + float G = nv::clamp(g[i] * irange, 0.0f, 1.0f); + float B = nv::clamp(b[i] * irange, 0.0f, 1.0f); - float m = max(max(ri, gi), max(bi, 1e-6f)); // Avoid division by zero. + float M = max(max(R, G), max(B, 1e-6f)); // Avoid division by zero. //m = quantizeCeil(m, 8); - float im = 1.0f / m; - r[i] = ri * im; - g[i] = gi * im; - b[i] = bi * im; - a[i] = m; + r[i] = R / M; + g[i] = G / M; + b[i] = B / M; + a[i] = M; + } +} + +void TexImage::fromRGBM(float range/*= 1*/) +{ + if (m->image == NULL) return; + + detach(); + + FloatImage * img = m->image; + float * r = img->channel(0); + float * g = img->channel(1); + float * b = img->channel(2); + float * a = img->channel(3); + + const uint count = img->width() * img->height(); + for (uint i = 0; i < count; i++) { + float M = a[i] * range; + + r[i] *= M; + g[i] *= M; + b[i] *= M; + a[i] = 1.0f; } } + // Y is in the [0, 1] range, while CoCg are in the [-1, 1] range. void TexImage::toYCoCg() { @@ -1068,13 +1101,13 @@ void TexImage::toYCoCg() const uint count = img->width() * img->height(); for (uint i = 0; i < count; i++) { - float ri = r[i]; - float gi = g[i]; - float bi = b[i]; + float R = r[i]; + float G = g[i]; + float B = b[i]; - float Y = (2*gi + ri + bi) * 0.25f; - float Co = (ri - bi); - float Cg = (2*gi - ri - bi) * 0.5f; + float Y = (2*G + R + B) * 0.25f; + float Co = (R - B); + float Cg = (2*G - R - B) * 0.5f; r[i] = Co; g[i] = Cg; @@ -1146,6 +1179,40 @@ void TexImage::blockScaleCoCg(int bits/*= 5*/, float threshold/*= 0.0*/) } } +void TexImage::fromYCoCg() +{ + if (m->image == NULL) return; + + detach(); + + FloatImage * img = m->image; + float * r = img->channel(0); + float * g = img->channel(1); + float * b = img->channel(2); + float * a = img->channel(3); + + const uint count = img->width() * img->height(); + for (uint i = 0; i < count; i++) { + float Co = r[i]; + float Cg = g[i]; + float scale = b[i]; + float Y = a[i]; + + Co *= scale; + Cg *= scale; + + float R = Y + Co - Cg; + float G = Y + Cg; + float B = Y - Co - Cg; + + r[i] = R; + g[i] = G; + b[i] = B; + a[i] = 1.0f; + } +} + + void TexImage::binarize(int channel, float threshold, bool dither) { @@ -1189,12 +1256,51 @@ void TexImage::normalizeNormalMap() nv::normalizeNormalMap(m->image); } -float TexImage::rootMeanSquaredError_rgb(const TexImage & reference) const +void TexImage::flipVertically() +{ + if (m->image == NULL) return; + + detach(); + + m->image->flip(); +} + +bool TexImage::copyChannel(const TexImage & srcImage, int srcChannel) +{ + return copyChannel(srcImage, srcChannel, srcChannel); +} + +bool TexImage::copyChannel(const TexImage & srcImage, int srcChannel, int dstChannel) +{ + if (srcChannel < 0 || srcChannel > 3 || dstChannel < 0 || dstChannel > 3) return false; + + FloatImage * dst = m->image; + const FloatImage * src = srcImage.m->image; + + if (dst == NULL || src == NULL || dst->width() != src->width() || dst->height() != src->height()) { + return false; + } + nvDebugCheck(dst->componentNum() == 4 && src->componentNum() == 4); + + detach(); + + const uint w = src->width(); + const uint h = src->height(); + + memcpy(dst->channel(dstChannel), src->channel(srcChannel), w*h*sizeof(float)); + + return true; +} + + + + +float nvtt::rmsError(const TexImage & reference, const TexImage & image) { double mse = 0; - const FloatImage * img = m->image; const FloatImage * ref = reference.m->image; + const FloatImage * img = image.m->image; if (img == NULL || ref == NULL || img->width() != ref->width() || img->height() != ref->height()) { return FLT_MAX; @@ -1205,14 +1311,14 @@ float TexImage::rootMeanSquaredError_rgb(const TexImage & reference) const const uint count = img->width() * img->height(); for (uint i = 0; i < count; i++) { - float r0 = img->pixel(4 * i + count * 0); - float g0 = img->pixel(4 * i + count * 1); - float b0 = img->pixel(4 * i + count * 2); - //float a0 = img->pixel(4 * i + count * 3); - float r1 = ref->pixel(4 * i + count * 0); - float g1 = ref->pixel(4 * i + count * 1); - float b1 = ref->pixel(4 * i + count * 2); - float a1 = ref->pixel(4 * i + count * 3); + float r0 = img->pixel(i + count * 0); + float g0 = img->pixel(i + count * 1); + float b0 = img->pixel(i + count * 2); + //float a0 = img->pixel(i + count * 3); + float r1 = ref->pixel(i + count * 0); + float g1 = ref->pixel(i + count * 1); + float b1 = ref->pixel(i + count * 2); + float a1 = ref->pixel(i + count * 3); float r = r0 - r1; float g = g0 - g1; @@ -1221,9 +1327,9 @@ float TexImage::rootMeanSquaredError_rgb(const TexImage & reference) const if (reference.alphaMode() == nvtt::AlphaMode_Transparency) { - mse += double(r * r) * a1 / 255.0; - mse += double(g * g) * a1 / 255.0; - mse += double(b * b) * a1 / 255.0; + mse += double(r * r) * a1; + mse += double(g * g) * a1; + mse += double(b * b) * a1; } else { @@ -1236,11 +1342,42 @@ float TexImage::rootMeanSquaredError_rgb(const TexImage & reference) const return float(sqrt(mse / count)); } -float TexImage::rootMeanSquaredError_alpha(const TexImage & reference) const + +/*float rmsError(const Image * a, const Image * b) { + nvCheck(a != NULL); + nvCheck(b != NULL); + nvCheck(a->width() == b->width()); + nvCheck(a->height() == b->height()); + double mse = 0; - const FloatImage * img = m->image; + const uint count = a->width() * a->height(); + + for (uint i = 0; i < count; i++) + { + Color32 c0 = a->pixel(i); + Color32 c1 = b->pixel(i); + + int r = c0.r - c1.r; + int g = c0.g - c1.g; + int b = c0.b - c1.b; + int a = c0.a - c1.a; + + mse += double(r * r * c0.a) / 255; + mse += double(g * g * c0.a) / 255; + mse += double(b * b * c0.a) / 255; + } + + return float(sqrt(mse / count)); +}*/ + + +float nvtt::rmsAlphaError(const TexImage & reference, const TexImage & image) +{ + double mse = 0; + + const FloatImage * img = image.m->image; const FloatImage * ref = reference.m->image; if (img == NULL || ref == NULL || img->width() != ref->width() || img->height() != ref->height()) { @@ -1251,8 +1388,8 @@ float TexImage::rootMeanSquaredError_alpha(const TexImage & reference) const const uint count = img->width() * img->height(); for (uint i = 0; i < count; i++) { - float a0 = img->pixel(4 * i + count * 3); - float a1 = ref->pixel(4 * i + count * 3); + float a0 = img->pixel(i + count * 3); + float a1 = ref->pixel(i + count * 3); float a = a0 - a1; @@ -1262,40 +1399,11 @@ float TexImage::rootMeanSquaredError_alpha(const TexImage & reference) const return float(sqrt(mse / count)); } -void TexImage::flipVertically() -{ - if (m->image == NULL) return; - - detach(); - - m->image->flip(); -} - -bool TexImage::copyChannel(const TexImage & srcImage, int srcChannel) +TexImage nvtt::diff(const TexImage & reference, const TexImage & image) { - return copyChannel(srcImage, srcChannel, srcChannel); + // @@ TODO. + return TexImage(); } -bool TexImage::copyChannel(const TexImage & srcImage, int srcChannel, int dstChannel) -{ - if (srcChannel < 0 || srcChannel > 3 || dstChannel < 0 || dstChannel > 3) return false; - - FloatImage * dst = m->image; - const FloatImage * src = srcImage.m->image; - - if (dst == NULL || src == NULL || dst->width() != src->width() || dst->height() != src->height()) { - return false; - } - nvDebugCheck(dst->componentNum() == 4 && src->componentNum() == 4); - - detach(); - - const uint w = src->width(); - const uint h = src->height(); - - memcpy(dst->channel(dstChannel), src->channel(srcChannel), w*h*sizeof(float)); - - return true; -} diff --git a/src/nvtt/TexImage.h b/src/nvtt/TexImage.h index 3125584..5f95e56 100644 --- a/src/nvtt/TexImage.h +++ b/src/nvtt/TexImage.h @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/cuda/CompressKernel.cu b/src/nvtt/cuda/CompressKernel.cu index e63ae61..efa61fa 100644 --- a/src/nvtt/cuda/CompressKernel.cu +++ b/src/nvtt/cuda/CompressKernel.cu @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/cuda/ConvolveKernel.cu b/src/nvtt/cuda/ConvolveKernel.cu index 35f684d..d87f36b 100644 --- a/src/nvtt/cuda/ConvolveKernel.cu +++ b/src/nvtt/cuda/ConvolveKernel.cu @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/cuda/CudaCompressorDXT.cpp b/src/nvtt/cuda/CudaCompressorDXT.cpp index 1124bb5..b27f515 100644 --- a/src/nvtt/cuda/CudaCompressorDXT.cpp +++ b/src/nvtt/cuda/CudaCompressorDXT.cpp @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -133,11 +134,11 @@ void CudaCompressor::compress(nvtt::AlphaMode alphaMode, uint w, uint h, const f // Allocate image as a cuda array. const uint count = w * h; Color32 * tmp = malloc(count); - for (int i = 0; i < count; i++) { - tmp[i].r = clamp(data[i + count*0], 0.0f, 1.0f) * 255; - tmp[i].g = clamp(data[i + count*1], 0.0f, 1.0f) * 255; - tmp[i].b = clamp(data[i + count*2], 0.0f, 1.0f) * 255; - tmp[i].a = clamp(data[i + count*3], 0.0f, 1.0f) * 255; + for (uint i = 0; i < count; i++) { + tmp[i].r = uint8(clamp(data[i + count*0], 0.0f, 1.0f) * 255); + tmp[i].g = uint8(clamp(data[i + count*1], 0.0f, 1.0f) * 255); + tmp[i].b = uint8(clamp(data[i + count*2], 0.0f, 1.0f) * 255); + tmp[i].a = uint8(clamp(data[i + count*3], 0.0f, 1.0f) * 255); } cudaArray * d_image; diff --git a/src/nvtt/cuda/CudaCompressorDXT.h b/src/nvtt/cuda/CudaCompressorDXT.h index 582b0e2..c6d1314 100644 --- a/src/nvtt/cuda/CudaCompressorDXT.h +++ b/src/nvtt/cuda/CudaCompressorDXT.h @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/cuda/CudaMath.h b/src/nvtt/cuda/CudaMath.h index c8d1a56..c3992f1 100644 --- a/src/nvtt/cuda/CudaMath.h +++ b/src/nvtt/cuda/CudaMath.h @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/cuda/CudaUtils.cpp b/src/nvtt/cuda/CudaUtils.cpp index d815090..e880f8b 100644 --- a/src/nvtt/cuda/CudaUtils.cpp +++ b/src/nvtt/cuda/CudaUtils.cpp @@ -1,239 +1,240 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -#include "nvcore/Debug.h" -#include "nvcore/Library.h" -#include "CudaUtils.h" - -#if defined HAVE_CUDA -#include -#include -#endif - -using namespace nv; -using namespace cuda; - -/* @@ Move this to win32 utils or somewhere else. -#if NV_OS_WIN32 - -#define WINDOWS_LEAN_AND_MEAN -#include - -static bool isWindowsVista() -{ - OSVERSIONINFO osvi; - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - - ::GetVersionEx(&osvi); - return osvi.dwMajorVersion >= 6; -} - - -typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); - -static bool isWow32() -{ - LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle("kernel32"), "IsWow64Process"); - - BOOL bIsWow64 = FALSE; - - if (NULL != fnIsWow64Process) - { - if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) - { - // Assume 32 bits. - return true; - } - } - - return !bIsWow64; -} - -#endif -*/ - - -static bool isCudaDriverAvailable(int version) -{ -#if defined HAVE_CUDA -#if NV_OS_WIN32 - Library nvcuda("nvcuda.dll"); -#else - Library nvcuda(NV_LIBRARY_NAME(cuda)); -#endif - - if (!nvcuda.isValid()) - { - nvDebug("*** CUDA driver not found.\n"); - return false; - } - - if (version >= 2000) - { - void * address = nvcuda.bindSymbol("cuStreamCreate"); - if (address == NULL) { - nvDebug("*** CUDA driver version < 2.0.\n"); - return false; - } - } - - if (version >= 2010) - { - void * address = nvcuda.bindSymbol("cuModuleLoadDataEx"); - if (address == NULL) { - nvDebug("*** CUDA driver version < 2.1.\n"); - return false; - } - } - - if (version >= 2020) - { - typedef CUresult (CUDAAPI * PFCU_DRIVERGETVERSION)(int * version); - - PFCU_DRIVERGETVERSION driverGetVersion = (PFCU_DRIVERGETVERSION)nvcuda.bindSymbol("cuDriverGetVersion"); - if (driverGetVersion == NULL) { - nvDebug("*** CUDA driver version < 2.2.\n"); - return false; - } - - int driverVersion; - CUresult err = driverGetVersion(&driverVersion); - if (err != CUDA_SUCCESS) { - nvDebug("*** Error querying driver version: '%s'.\n", cudaGetErrorString((cudaError_t)err)); - return false; - } - - return driverVersion >= version; - } -#endif // HAVE_CUDA - - return true; -} - - -/// Determine if CUDA is available. -bool nv::cuda::isHardwarePresent() -{ -#if defined HAVE_CUDA - // Make sure that CUDA driver matches CUDA runtime. - if (!isCudaDriverAvailable(CUDART_VERSION)) - { - nvDebug("CUDA driver not available for CUDA runtime %d\n", CUDART_VERSION); - return false; - } - - int count = deviceCount(); - if (count == 1) - { - // Make sure it's not an emulation device. - cudaDeviceProp deviceProp; - cudaGetDeviceProperties(&deviceProp, 0); - - // deviceProp.name != Device Emulation (CPU) - if (deviceProp.major == -1 || deviceProp.minor == -1) - { - return false; - } - } - - // @@ Make sure that warp size == 32 - - return count > 0; -#else - return false; -#endif -} - -/// Get number of CUDA enabled devices. -int nv::cuda::deviceCount() -{ -#if defined HAVE_CUDA - int gpuCount = 0; - - cudaError_t result = cudaGetDeviceCount(&gpuCount); - - if (result == cudaSuccess) - { - return gpuCount; - } -#endif - return 0; -} - -int nv::cuda::getFastestDevice() -{ - int max_gflops_device = 0; -#if defined HAVE_CUDA - int max_gflops = 0; - - const int device_count = deviceCount(); - int current_device = 0; - while (current_device < device_count) - { - cudaDeviceProp device_properties; - cudaGetDeviceProperties(&device_properties, current_device); - int gflops = device_properties.multiProcessorCount * device_properties.clockRate; - - if (device_properties.major != -1 && device_properties.minor != -1) - { - if( gflops > max_gflops ) - { - max_gflops = gflops; - max_gflops_device = current_device; - } - } - - current_device++; - } -#endif - return max_gflops_device; -} - - -/// Activate the given devices. -bool nv::cuda::setDevice(int i) -{ - nvCheck(i < deviceCount()); -#if defined HAVE_CUDA - cudaError_t result = cudaSetDevice(i); - - if (result != cudaSuccess) { - nvDebug("*** CUDA Error: %s\n", cudaGetErrorString(result)); - } - - return result == cudaSuccess; -#else - return false; -#endif -} - -void nv::cuda::exit() -{ -#if defined HAVE_CUDA - cudaError_t result = cudaThreadExit(); - - if (result != cudaSuccess) { - nvDebug("*** CUDA Error: %s\n", cudaGetErrorString(result)); - } -#endif -} +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#include "nvcore/Debug.h" +#include "nvcore/Library.h" +#include "CudaUtils.h" + +#if defined HAVE_CUDA +#include +#include +#endif + +using namespace nv; +using namespace cuda; + +/* @@ Move this to win32 utils or somewhere else. +#if NV_OS_WIN32 + +#define WINDOWS_LEAN_AND_MEAN +#include + +static bool isWindowsVista() +{ + OSVERSIONINFO osvi; + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + ::GetVersionEx(&osvi); + return osvi.dwMajorVersion >= 6; +} + + +typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); + +static bool isWow32() +{ + LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle("kernel32"), "IsWow64Process"); + + BOOL bIsWow64 = FALSE; + + if (NULL != fnIsWow64Process) + { + if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) + { + // Assume 32 bits. + return true; + } + } + + return !bIsWow64; +} + +#endif +*/ + + +static bool isCudaDriverAvailable(int version) +{ +#if defined HAVE_CUDA +#if NV_OS_WIN32 + Library nvcuda("nvcuda.dll"); +#else + Library nvcuda(NV_LIBRARY_NAME(cuda)); +#endif + + if (!nvcuda.isValid()) + { + nvDebug("*** CUDA driver not found.\n"); + return false; + } + + if (version >= 2000) + { + void * address = nvcuda.bindSymbol("cuStreamCreate"); + if (address == NULL) { + nvDebug("*** CUDA driver version < 2.0.\n"); + return false; + } + } + + if (version >= 2010) + { + void * address = nvcuda.bindSymbol("cuModuleLoadDataEx"); + if (address == NULL) { + nvDebug("*** CUDA driver version < 2.1.\n"); + return false; + } + } + + if (version >= 2020) + { + typedef CUresult (CUDAAPI * PFCU_DRIVERGETVERSION)(int * version); + + PFCU_DRIVERGETVERSION driverGetVersion = (PFCU_DRIVERGETVERSION)nvcuda.bindSymbol("cuDriverGetVersion"); + if (driverGetVersion == NULL) { + nvDebug("*** CUDA driver version < 2.2.\n"); + return false; + } + + int driverVersion; + CUresult err = driverGetVersion(&driverVersion); + if (err != CUDA_SUCCESS) { + nvDebug("*** Error querying driver version: '%s'.\n", cudaGetErrorString((cudaError_t)err)); + return false; + } + + return driverVersion >= version; + } +#endif // HAVE_CUDA + + return true; +} + + +/// Determine if CUDA is available. +bool nv::cuda::isHardwarePresent() +{ +#if defined HAVE_CUDA + // Make sure that CUDA driver matches CUDA runtime. + if (!isCudaDriverAvailable(CUDART_VERSION)) + { + nvDebug("CUDA driver not available for CUDA runtime %d\n", CUDART_VERSION); + return false; + } + + int count = deviceCount(); + if (count == 1) + { + // Make sure it's not an emulation device. + cudaDeviceProp deviceProp; + cudaGetDeviceProperties(&deviceProp, 0); + + // deviceProp.name != Device Emulation (CPU) + if (deviceProp.major == -1 || deviceProp.minor == -1) + { + return false; + } + } + + // @@ Make sure that warp size == 32 + + return count > 0; +#else + return false; +#endif +} + +/// Get number of CUDA enabled devices. +int nv::cuda::deviceCount() +{ +#if defined HAVE_CUDA + int gpuCount = 0; + + cudaError_t result = cudaGetDeviceCount(&gpuCount); + + if (result == cudaSuccess) + { + return gpuCount; + } +#endif + return 0; +} + +int nv::cuda::getFastestDevice() +{ + int max_gflops_device = 0; +#if defined HAVE_CUDA + int max_gflops = 0; + + const int device_count = deviceCount(); + int current_device = 0; + while (current_device < device_count) + { + cudaDeviceProp device_properties; + cudaGetDeviceProperties(&device_properties, current_device); + int gflops = device_properties.multiProcessorCount * device_properties.clockRate; + + if (device_properties.major != -1 && device_properties.minor != -1) + { + if( gflops > max_gflops ) + { + max_gflops = gflops; + max_gflops_device = current_device; + } + } + + current_device++; + } +#endif + return max_gflops_device; +} + + +/// Activate the given devices. +bool nv::cuda::setDevice(int i) +{ + nvCheck(i < deviceCount()); +#if defined HAVE_CUDA + cudaError_t result = cudaSetDevice(i); + + if (result != cudaSuccess) { + nvDebug("*** CUDA Error: %s\n", cudaGetErrorString(result)); + } + + return result == cudaSuccess; +#else + return false; +#endif +} + +void nv::cuda::exit() +{ +#if defined HAVE_CUDA + cudaError_t result = cudaThreadExit(); + + if (result != cudaSuccess) { + nvDebug("*** CUDA Error: %s\n", cudaGetErrorString(result)); + } +#endif +} diff --git a/src/nvtt/cuda/CudaUtils.h b/src/nvtt/cuda/CudaUtils.h index 376bbe1..f791c81 100644 --- a/src/nvtt/cuda/CudaUtils.h +++ b/src/nvtt/cuda/CudaUtils.h @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/nvtt.cpp b/src/nvtt/nvtt.cpp index 2885506..5698b27 100644 --- a/src/nvtt/nvtt.cpp +++ b/src/nvtt/nvtt.cpp @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/nvtt.h b/src/nvtt/nvtt.h index 5b18c1f..5f8cf99 100644 --- a/src/nvtt/nvtt.h +++ b/src/nvtt/nvtt.h @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -350,11 +351,11 @@ namespace nvtt // TexImage API. NVTT_API bool outputHeader(const TexImage & tex, int mipmapCount, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const; - NVTT_API bool compress(const TexImage & tex, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const; + NVTT_API bool compress(const TexImage & tex, int face, int mipmap, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const; NVTT_API int estimateSize(const TexImage & tex, int mipmapCount, const CompressionOptions & compressionOptions) const; // Raw API. - NVTT_API bool compress(int w, int h, int d, const float * rgba, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const; + NVTT_API bool compress(int w, int h, int d, int face, int mipmap, const float * rgba, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const; NVTT_API int estimateSize(int w, int h, int d, int mipmapCount, const CompressionOptions & compressionOptions) const; }; @@ -427,8 +428,10 @@ namespace nvtt NVTT_API void scaleAlphaToCoverage(float coverage, float alphaRef = 0.5f); NVTT_API bool normalizeRange(float * rangeMin, float * rangeMax); NVTT_API void toRGBM(float range = 1.0f, float threshold = 0.0f); + NVTT_API void fromRGBM(float range = 1.0f); NVTT_API void toYCoCg(); NVTT_API void blockScaleCoCg(int bits = 5, float threshold = 0.0f); + NVTT_API void fromYCoCg(); // Color quantization. NVTT_API void binarize(int channel, float threshold, bool dither); @@ -438,10 +441,6 @@ namespace nvtt NVTT_API void toNormalMap(float sm, float medium, float big, float large); NVTT_API void normalizeNormalMap(); - // Error compare. - NVTT_API float rootMeanSquaredError_rgb(const TexImage & reference) const; - NVTT_API float rootMeanSquaredError_alpha(const TexImage & reference) const; - // Geometric transforms. NVTT_API void flipVertically(); @@ -449,6 +448,11 @@ namespace nvtt NVTT_API bool copyChannel(const TexImage & srcImage, int srcChannel); NVTT_API bool copyChannel(const TexImage & srcImage, int srcChannel, int dstChannel); + // Error compare. + friend NVTT_API float rmsError(const TexImage & reference, const TexImage & img); + friend NVTT_API float rmsAlphaError(const TexImage & reference, const TexImage & img); + friend NVTT_API TexImage diff(const TexImage & reference, const TexImage & img); + private: void detach(); diff --git a/src/nvtt/nvtt_wrapper.cpp b/src/nvtt/nvtt_wrapper.cpp index 08ca1fd..36be3f6 100644 --- a/src/nvtt/nvtt_wrapper.cpp +++ b/src/nvtt/nvtt_wrapper.cpp @@ -1,3 +1,26 @@ +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. #include "nvtt.h" #include "nvtt_wrapper.h" diff --git a/src/nvtt/nvtt_wrapper.h b/src/nvtt/nvtt_wrapper.h index b74ff94..ac45b01 100644 --- a/src/nvtt/nvtt_wrapper.h +++ b/src/nvtt/nvtt_wrapper.h @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation diff --git a/src/nvtt/tests/imperativeapi.cpp b/src/nvtt/tests/imperativeapi.cpp index beb8204..98a29bf 100644 --- a/src/nvtt/tests/imperativeapi.cpp +++ b/src/nvtt/tests/imperativeapi.cpp @@ -64,7 +64,7 @@ int main(int argc, char *argv[]) image.setAlphaMode(nvtt::AlphaMode_Transparency); // Output first mipmap. - context.compress(image, compressionOptions, outputOptions); + context.compress(image, 0, 0, compressionOptions, outputOptions); float gamma = 2.2f; image.toLinear(gamma); @@ -73,6 +73,7 @@ int main(int argc, char *argv[]) float coverage = image.alphaTestCoverage(alphaRef); // Build mimaps. + int m = 1; while (image.buildNextMipmap(nvtt::MipmapFilter_Kaiser)) { nvtt::TexImage tmpImage = image; @@ -80,7 +81,8 @@ int main(int argc, char *argv[]) tmpImage.scaleAlphaToCoverage(coverage, alphaRef); - context.compress(tmpImage, compressionOptions, outputOptions); + context.compress(tmpImage, 0, m, compressionOptions, outputOptions); + m++; } return EXIT_SUCCESS; diff --git a/src/nvtt/tests/testsuite.cpp b/src/nvtt/tests/testsuite.cpp index ac7dd2f..63a5dc3 100644 --- a/src/nvtt/tests/testsuite.cpp +++ b/src/nvtt/tests/testsuite.cpp @@ -1,4 +1,5 @@ -// Copyright NVIDIA Corporation 2007 -- Ignacio Castano +// Copyright (c) 2009-2011 Ignacio Castano +// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -127,30 +128,39 @@ static const char * s_quake3ImageSet[] = { "q3-wires02.tga", }; - +enum Mode { + Mode_BC1, + Mode_BC3_Alpha, + Mode_BC3_YCoCg, + Mode_BC3_RGBM, + Mode_BC3_Normal, + Mode_BC5_Normal, +}; struct ImageSet { + const char * name; const char ** fileNames; int fileCount; - nvtt::Format format; + Mode mode; }; +#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0]) + static ImageSet s_imageSets[] = { - {s_kodakImageSet, sizeof(s_kodakImageSet)/sizeof(s_kodakImageSet[0]), nvtt::Format_DXT1}, - {s_waterlooImageSet, sizeof(s_waterlooImageSet)/sizeof(s_waterlooImageSet[0]), nvtt::Format_DXT1}, - {s_epicImageSet, sizeof(s_epicImageSet)/sizeof(s_epicImageSet[0]), nvtt::Format_DXT1}, - {s_farbrauschImageSet, sizeof(s_farbrauschImageSet)/sizeof(s_farbrauschImageSet[0]), nvtt::Format_DXT1}, - {s_lugaruImageSet, sizeof(s_lugaruImageSet)/sizeof(s_lugaruImageSet[0]), nvtt::Format_DXT5}, - {s_quake3ImageSet, sizeof(s_quake3ImageSet)/sizeof(s_quake3ImageSet[0]), nvtt::Format_DXT5}, + {"Kodak - BC1", s_kodakImageSet, ARRAY_SIZE(s_kodakImageSet), Mode_BC1}, + {"Kodak - BC3-YCoCg", s_kodakImageSet, ARRAY_SIZE(s_kodakImageSet), Mode_BC3_YCoCg}, + {"Kodak - BC3-RGBM", s_kodakImageSet, ARRAY_SIZE(s_kodakImageSet), Mode_BC3_RGBM}, + {"Waterloo - BC1", s_waterlooImageSet, ARRAY_SIZE(s_waterlooImageSet), Mode_BC1}, + {"Waterloo - BC3-YCoCg", s_waterlooImageSet, ARRAY_SIZE(s_waterlooImageSet), Mode_BC3_YCoCg}, + {"Epic - BC1", s_epicImageSet, ARRAY_SIZE(s_epicImageSet), Mode_BC1}, + {"Epic - BC1-YCoCg", s_epicImageSet, ARRAY_SIZE(s_epicImageSet), Mode_BC3_YCoCg}, + {"Farbraush - BC1", s_farbrauschImageSet, ARRAY_SIZE(s_farbrauschImageSet), Mode_BC1}, + {"Farbraush - BC1-YCoCg", s_farbrauschImageSet, ARRAY_SIZE(s_farbrauschImageSet), Mode_BC3_YCoCg}, + {"Lugaru - BC3", s_lugaruImageSet, ARRAY_SIZE(s_lugaruImageSet), Mode_BC3_Alpha}, + {"Quake3 - BC3", s_quake3ImageSet, ARRAY_SIZE(s_quake3ImageSet), Mode_BC3_Alpha}, }; const int s_imageSetCount = sizeof(s_imageSets)/sizeof(s_imageSets[0]); -enum Decoder -{ - Decoder_Reference, - Decoder_NVIDIA, -}; - struct MyOutputHandler : public nvtt::OutputHandler { MyOutputHandler() : m_data(NULL), m_ptr(NULL) {} @@ -176,83 +186,17 @@ struct MyOutputHandler : public nvtt::OutputHandler return true; } - Image * decompress(nvtt::Format format, Decoder decoder) + nvtt::TexImage decompress(Mode mode, nvtt::Decoder decoder) { - int bw = (m_width + 3) / 4; - int bh = (m_height + 3) / 4; - - AutoPtr img( new Image() ); - img->allocate(m_width, m_height); - - if (format == nvtt::Format_BC1) - { - BlockDXT1 * block = (BlockDXT1 *)m_data; - - for (int y = 0; y < bh; y++) - { - for (int x = 0; x < bw; x++) - { - ColorBlock colors; - if (decoder == Decoder_Reference) { - block->decodeBlock(&colors); - } - else if (decoder == Decoder_NVIDIA) { - block->decodeBlockNV5x(&colors); - } - - for (int yy = 0; yy < 4; yy++) - { - for (int xx = 0; xx < 4; xx++) - { - Color32 c = colors.color(xx, yy); - - if (x * 4 + xx < m_width && y * 4 + yy < m_height) - { - img->pixel(x * 4 + xx, y * 4 + yy) = c; - } - } - } - - block++; - } - } - } - else if (format == nvtt::Format_BC3) - { - BlockDXT5 * block = (BlockDXT5 *)m_data; + nvtt::Format format; + if (mode == Mode_BC1) format = nvtt::Format_BC1; + else if (mode == Mode_BC5_Normal) format = nvtt::Format_BC5; + else format = nvtt::Format_BC3; - for (int y = 0; y < bh; y++) - { - for (int x = 0; x < bw; x++) - { - ColorBlock colors; - if (decoder == Decoder_Reference) { - block->decodeBlock(&colors); - } - else if (decoder == Decoder_NVIDIA) { - block->decodeBlockNV5x(&colors); - } - - for (int yy = 0; yy < 4; yy++) - { - for (int xx = 0; xx < 4; xx++) - { - Color32 c = colors.color(xx, yy); - - if (x * 4 + xx < m_width && y * 4 + yy < m_height) - { - img->pixel(x * 4 + xx, y * 4 + yy) = c; - } - } - } - - block++; - } - } - } + nvtt::TexImage img; + img.setImage2D(format, decoder, m_width, m_height, m_data); - - return img.release(); + return img; } int m_size; @@ -263,36 +207,6 @@ struct MyOutputHandler : public nvtt::OutputHandler }; -float rmsError(const Image * a, const Image * b) -{ - nvCheck(a != NULL); - nvCheck(b != NULL); - nvCheck(a->width() == b->width()); - nvCheck(a->height() == b->height()); - - double mse = 0; - - const uint count = a->width() * a->height(); - - for (uint i = 0; i < count; i++) - { - Color32 c0 = a->pixel(i); - Color32 c1 = b->pixel(i); - - int r = c0.r - c1.r; - int g = c0.g - c1.g; - int b = c0.b - c1.b; - int a = c0.a - c1.a; - - mse += double(r * r * c0.a) / 255; - mse += double(g * g * c0.a) / 255; - mse += double(b * b * c0.a) / 255; - } - - return float(sqrt(mse / count)); -} - - int main(int argc, char *argv[]) { MyAssertHandler assertHandler; @@ -305,11 +219,11 @@ int main(int argc, char *argv[]) printf("NVIDIA Texture Tools %u.%u.%u - Copyright NVIDIA Corporation 2007\n\n", major, minor, rev); - int set = 0; + int setIndex = 0; bool fast = false; bool nocuda = false; bool showHelp = false; - Decoder decoder = Decoder_Reference; + nvtt::Decoder decoder = nvtt::Decoder_Reference; const char * basePath = ""; const char * outPath = "output"; const char * regressPath = NULL; @@ -320,14 +234,14 @@ int main(int argc, char *argv[]) if (strcmp("-set", argv[i]) == 0) { if (i+1 < argc && argv[i+1][0] != '-') { - set = atoi(argv[i+1]); + setIndex = atoi(argv[i+1]); i++; } } else if (strcmp("-dec", argv[i]) == 0) { if (i+1 < argc && argv[i+1][0] != '-') { - decoder = (Decoder)atoi(argv[i+1]); + decoder = (nvtt::Decoder)atoi(argv[i+1]); i++; } } @@ -394,10 +308,6 @@ int main(int argc, char *argv[]) return 1; } - nvtt::InputOptions inputOptions; - inputOptions.setMipmapGeneration(false); - inputOptions.setAlphaMode(nvtt::AlphaMode_Transparency); - nvtt::CompressionOptions compressionOptions; compressionOptions.setFormat(nvtt::Format_BC1); if (fast) @@ -413,7 +323,22 @@ int main(int argc, char *argv[]) //compressionOptions.setExternalCompressor("d3dx"); //compressionOptions.setExternalCompressor("stb"); - compressionOptions.setFormat(s_imageSets[set].format); + + const ImageSet & set = s_imageSets[setIndex]; + + if (set.mode == Mode_BC1) { + compressionOptions.setFormat(nvtt::Format_BC1); + } + else if (set.mode == Mode_BC3_Alpha || set.mode == Mode_BC3_YCoCg || set.mode == Mode_BC3_RGBM) { + compressionOptions.setFormat(nvtt::Format_BC3); + } + else if (set.mode == Mode_BC3_Normal) { + compressionOptions.setFormat(nvtt::Format_BC3n); + } + else if (set.mode == Mode_BC5_Normal) { + compressionOptions.setFormat(nvtt::Format_BC5); + } + nvtt::OutputOptions outputOptions; @@ -429,7 +354,7 @@ int main(int argc, char *argv[]) FileSystem::createDirectory(outPath); Path csvFileName; - csvFileName.format("%s/result-%d.csv", outPath, set); + csvFileName.format("%s/result-%d.csv", outPath, setIndex); StdOutputStream csvStream(csvFileName.str()); TextWriter csvWriter(&csvStream); @@ -438,46 +363,85 @@ int main(int argc, char *argv[]) int failedTests = 0; float totalDiff = 0; - const char ** fileNames = s_imageSets[set].fileNames; - int fileCount = s_imageSets[set].fileCount; + const char ** fileNames = set.fileNames; + int fileCount = set.fileCount; Timer timer; + nvtt::TexImage img; + if (set.mode == Mode_BC3_Alpha) { + img.setAlphaMode(nvtt::AlphaMode_Transparency); + } + if (set.mode == Mode_BC3_Normal || set.mode == Mode_BC5_Normal) { + img.setNormalMap(true); + } + + printf("Processing Set: %s\n", set.name); + for (int i = 0; i < fileCount; i++) { - AutoPtr img( new Image() ); - - if (!img->load(fileNames[i])) + if (!img.load(fileNames[i])) { printf("Input image '%s' not found.\n", fileNames[i]); return EXIT_FAILURE; } - inputOptions.setTextureLayout(nvtt::TextureType_2D, img->width(), img->height()); - inputOptions.setMipmapData(img->pixels(), img->width(), img->height()); + if (img.isNormalMap()) { + img.normalizeNormalMap(); + } + + if (set.mode == Mode_BC3_YCoCg) { + img.toYCoCg(); + img.blockScaleCoCg(); + img.scaleBias(0, 0.5, 0.5); + img.scaleBias(1, 0.5, 0.5); + } + else if (set.mode == Mode_BC3_RGBM) { + img.toRGBM(); + } printf("Compressing: \t'%s'\n", fileNames[i]); timer.start(); - context.process(inputOptions, compressionOptions, outputOptions); + context.compress(img, 0, 0, compressionOptions, outputOptions); timer.stop(); printf(" Time: \t%.3f sec\n", timer.elapsed()); totalTime += timer.elapsed(); - AutoPtr img_out( outputHandler.decompress(s_imageSets[set].format, decoder) ); + nvtt::TexImage img_out = outputHandler.decompress(set.mode, decoder); + if (set.mode == Mode_BC3_Alpha) { + img_out.setAlphaMode(nvtt::AlphaMode_Transparency); + } + if (set.mode == Mode_BC3_Normal || set.mode == Mode_BC5_Normal) { + img_out.setNormalMap(true); + } + + if (set.mode == Mode_BC3_YCoCg) { + img_out.scaleBias(0, 1.0, -0.5); + img_out.scaleBias(1, 1.0, -0.5); + img_out.fromYCoCg(); + + img.scaleBias(0, 1.0, -0.5); + img.scaleBias(1, 1.0, -0.5); + img.fromYCoCg(); + } + else if (set.mode == Mode_BC3_RGBM) { + img_out.fromRGBM(); + img.fromRGBM(); + } Path outputFileName; outputFileName.format("%s/%s", outPath, fileNames[i]); outputFileName.stripExtension(); outputFileName.append(".png"); - if (!ImageIO::save(outputFileName.str(), img_out.ptr())) + if (!img_out.save(outputFileName.str())) { printf("Error saving file '%s'.\n", outputFileName.str()); } - float rmse = rmsError(img.ptr(), img_out.ptr()); + float rmse = nvtt::rmsError(img, img_out); totalRMSE += rmse; printf(" RMSE: \t%.4f\n", rmse); @@ -492,14 +456,14 @@ int main(int argc, char *argv[]) regressFileName.stripExtension(); regressFileName.append(".png"); - AutoPtr img_reg( new Image() ); - if (!img_reg->load(regressFileName.str())) + nvtt::TexImage img_reg; + if (!img_reg.load(regressFileName.str())) { printf("Regression image '%s' not found.\n", regressFileName.str()); return EXIT_FAILURE; } - float rmse_reg = rmsError(img.ptr(), img_reg.ptr()); + float rmse_reg = rmsError(img, img_reg); float diff = rmse_reg - rmse; totalDiff += diff;