More work toward 2.1: Implement InputOptions using TexImage.

pull/216/head
castano 14 years ago
parent 8838b5220a
commit 1e2567e4a3

@ -35,7 +35,7 @@
# include <signal.h>
#endif
#if NV_OS_LINUX || NV_OS_DARWIN
#if NV_OS_LINUX || NV_OS_DARWIN || NV_OS_FREEBSD
# include <unistd.h> // getpid
#endif
@ -294,13 +294,13 @@ namespace
# if NV_CC_GNUC // defined(HAVE_CXXABI_H)
char * begin = strchr(string_array[i], '(');
char * end = strchr(string_array[i], '+');
if( begin != 0 && begin < end ) {
if (begin != 0 && begin < end) {
int stat;
*end = '\0';
*begin = '\0';
char * module = string_array[i];
char * name = abi::__cxa_demangle(begin+1, 0, 0, &stat);
if( name == NULL || begin[1] != '_' || begin[2] != 'Z' ) {
if (name == NULL || stat != 0) {
nvDebug( " In: [%s] '%s'\n", module, begin+1 );
}
else {

@ -166,8 +166,8 @@ namespace nv
inline float square(float f) { return f * f; }
inline int square(int i) { return i * i; }
inline float cube(float f) { return f * f; }
inline int cube(int i) { return i * i; }
inline float cube(float f) { return f * f * f; }
inline int cube(int i) { return i * i * i; }
// @@ Float to int conversions to be optimized at some point. See:
// http://cbloomrants.blogspot.com/2009/01/01-17-09-float-to-int.html
@ -194,6 +194,33 @@ namespace nv
return f - floor(f);
}
inline float fround(float f)
{
// @@ Do something better.
return float(iround(f));
}
inline float quantizeCeil(float f, int bits)
{
nvDebugCheck(f >= 0.0f && f <= 1.0f);
float scale = float(1 << bits);
return ceilf(f * scale) / scale;
}
inline float quantizeRound(float f, int bits)
{
nvDebugCheck(f >= 0.0f && f <= 1.0f);
float scale = float(1 << bits);
return fround(f * scale) / scale;
}
inline float quantizeFloor(float f, int bits)
{
nvDebugCheck(f >= 0.0f && f <= 1.0f);
float scale = float(1 << bits);
return floor(f * scale) / scale;
}
} // nv
#endif // NV_MATH_H

@ -32,7 +32,7 @@ namespace nv
struct CompressorInterface
{
virtual ~CompressorInterface() {}
virtual void compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, const void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions) = 0;
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * rgba, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions) = 0;
};
} // nv namespace

@ -95,13 +95,6 @@ namespace nv
// External compressors.
#if defined(HAVE_S3QUANT)
struct S3CompressorDXT1 : public CompressorInterface
{
virtual void compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
};
#endif
#if defined(HAVE_ATITC)
struct AtiCompressorDXT1 : public CompressorInterface
{

@ -44,7 +44,7 @@ using namespace nv;
using namespace nvtt;
void FixedBlockCompressor::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, const void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
void FixedBlockCompressor::compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
{
const uint bs = blockSize();
const uint bw = (w + 3) / 4;
@ -68,13 +68,7 @@ void FixedBlockCompressor::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMo
for (uint x = 0; x < w; x += 4) {
ColorBlock rgba;
if (inputFormat == nvtt::InputFormat_BGRA_8UB) {
rgba.init(w, h, (const uint *)data, x, y);
}
else {
nvDebugCheck(inputFormat == nvtt::InputFormat_RGBA_32F);
rgba.init(w, h, (const float *)data, x, y);
}
rgba.init(w, h, data, x, y);
compressBlock(rgba, alphaMode, compressionOptions, mem);
@ -99,13 +93,7 @@ void FixedBlockCompressor::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMo
const uint y = i / bw;
ColorBlock rgba;
if (inputFormat == nvtt::InputFormat_BGRA_8UB) {
rgba.init(w, h, (uint *)data, 4*x, 4*y);
}
else {
nvDebugCheck(inputFormat == nvtt::InputFormat_RGBA_32F);
rgba.init(w, h, (float *)data, 4*x, 4*y);
}
rgba.init(w, h, data, 4*x, 4*y);
uint8 * ptr = mem + (y * bw + x) * bs;
compressBlock(rgba, alphaMode, compressionOptions, ptr);
@ -124,7 +112,7 @@ void FixedBlockCompressor::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMo
#include "bc6h/tile.h"
void TileCompressor::compress(InputFormat inputFormat, AlphaMode alphaMode, uint w, uint h, const void * data, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions)
void TileCompressor::compress(AlphaMode alphaMode, uint w, uint h, const float * data, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions)
{
const uint bs = blockSize();
const uint bw = (w + 3) / 4;
@ -141,13 +129,7 @@ void TileCompressor::compress(InputFormat inputFormat, AlphaMode alphaMode, uint
for (uint x = 0; x < w; x += 4) {
Tile tile;
if (inputFormat == nvtt::InputFormat_BGRA_8UB) {
//tile.init((const uint *)data, w, h, x, y);
}
else {
nvDebugCheck(inputFormat == nvtt::InputFormat_RGBA_32F);
//tile.init((const float *)data, w, h, x, y);
}
compressBlock(tile, alphaMode, compressionOptions, mem);

@ -34,7 +34,7 @@ namespace nv
struct FixedBlockCompressor : public CompressorInterface
{
virtual void compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, const void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * rgba, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
virtual void compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) = 0;
virtual uint blockSize() const = 0;
@ -42,7 +42,7 @@ namespace nv
struct TileCompressor : public CompressorInterface
{
virtual void compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, const void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * rgba, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
virtual void compressBlock(Tile & tile, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) = 0;
virtual uint blockSize() const = 0;

@ -121,8 +121,10 @@ namespace
void PixelFormatConverter::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, const void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
void PixelFormatConverter::compress(nvtt::AlphaMode /*alphaMode*/, uint w, uint h, const float * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
{
nvDebugCheck (compressionOptions.format == nvtt::Format_RGBA);
uint bitCount;
uint rmask, rshift, rsize;
uint gmask, gshift, gsize;
@ -193,37 +195,14 @@ void PixelFormatConverter::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMo
const uint * src = (const uint *)data + y * w;
const float * fsrc = (const float *)data + y * w;
if (inputFormat == nvtt::InputFormat_BGRA_8UB && compressionOptions.pixelType == nvtt::PixelType_UnsignedNorm && bitCount == 32 && rmask == 0xFF0000 && gmask == 0xFF00 && bmask == 0xFF && amask == 0xFF000000)
{
convert_to_a8r8g8b8(src, dst, w);
}
else
{
BitStream stream(dst);
for (uint x = 0; x < w; x++)
{
float r, g, b, a;
if (inputFormat == nvtt::InputFormat_BGRA_8UB) {
Color32 c = Color32(src[x]);
r = float(c.r) / 255.0f;
g = float(c.g) / 255.0f;
b = float(c.b) / 255.0f;
a = float(c.a) / 255.0f;
}
else {
nvDebugCheck (inputFormat == nvtt::InputFormat_RGBA_32F);
//r = ((float *)src)[4 * x + 0]; // Color components not interleaved.
//g = ((float *)src)[4 * x + 1];
//b = ((float *)src)[4 * x + 2];
//a = ((float *)src)[4 * x + 3];
r = fsrc[x + 0 * wh];
g = fsrc[x + 1 * wh];
b = fsrc[x + 2 * wh];
a = fsrc[x + 3 * wh];
}
float r = fsrc[x + 0 * wh];
float g = fsrc[x + 1 * wh];
float b = fsrc[x + 2 * wh];
float a = fsrc[x + 3 * wh];
if (compressionOptions.pixelType == nvtt::PixelType_Float)
{
@ -274,7 +253,6 @@ void PixelFormatConverter::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMo
{
*(dst + x) = 0;
}*/
}
outputOptions.writeData(dst, pitch);
}

@ -30,7 +30,7 @@ namespace nv
{
struct PixelFormatConverter : public CompressorInterface
{
virtual void compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, const void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
};
} // nv namespace

@ -55,7 +55,7 @@ static Color32 toRgbe8(float r, float g, float b)
}
void CompressorRGBE::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, const void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
void CompressorRGBE::compress(nvtt::AlphaMode /*alphaMode*/, uint w, uint h, const float * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
{
nvDebugCheck (compressionOptions.format == nvtt::Format_RGBE);
@ -67,27 +67,13 @@ void CompressorRGBE::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alp
for (uint y = 0; y < h; y++)
{
const uint * src = (const uint *)data + y * srcPitch;
const float * fsrc = (const float *)data + y * srcPitch;
const float * src = (const float *)data + y * srcPitch;
for (uint x = 0; x < w; x++)
{
float r, g, b;
if (inputFormat == nvtt::InputFormat_BGRA_8UB) {
Color32 c = Color32(src[x]);
r = float(c.r) / 255.0f;
g = float(c.g) / 255.0f;
b = float(c.b) / 255.0f;
}
else {
nvDebugCheck (inputFormat == nvtt::InputFormat_RGBA_32F);
// Color components not interleaved.
r = fsrc[x + 0 * srcPlane];
g = fsrc[x + 1 * srcPlane];
b = fsrc[x + 2 * srcPlane];
}
float r = src[x + 0 * srcPlane];
float g = src[x + 1 * srcPlane];
float b = src[x + 2 * srcPlane];
dst[x] = toRgbe8(r, g, b);
}

@ -30,7 +30,7 @@ namespace nv
{
struct CompressorRGBE : public CompressorInterface
{
virtual void compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, const void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
};
} // nv namespace

File diff suppressed because it is too large Load Diff

@ -43,36 +43,31 @@ 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 compress2D(InputFormat inputFormat, AlphaMode alphaMode, int w, int h, const void * data, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const;
int estimateSize(const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions) const;
bool outputHeader(const TexImage & tex, int mipmapCount, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions);
private:
//int estimateSize(const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions) const;
bool outputHeader(const TexImage & tex, int mipmapCount, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const;
bool outputHeader(const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const;
nv::CompressorInterface * chooseCpuCompressor(const CompressionOptions::Private & compressionOptions) const;
nv::CompressorInterface * chooseGpuCompressor(const CompressionOptions::Private & compressionOptions) const;
bool compressMipmaps(uint f, const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const;
bool initMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions, uint w, uint h, uint d, uint f, uint m) const;
//bool compressMipmaps(uint f, const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const;
int findExactMipmap(const InputOptions::Private & inputOptions, uint w, uint h, uint d, uint f) const;
int findClosestMipmap(const InputOptions::Private & inputOptions, uint w, uint h, uint d, uint f) const;
//bool initMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions, uint w, uint h, uint d, uint f, uint m) const;
void downsampleMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions) const;
void scaleMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions, uint w, uint h, uint d) const;
void premultiplyAlphaMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions) const;
void processInputImage(Mipmap & mipmap, const InputOptions::Private & inputOptions) const;
void quantizeMipmap(Mipmap & mipmap, const CompressionOptions::Private & compressionOptions) const;
//int findExactMipmap(const InputOptions::Private & inputOptions, uint w, uint h, uint d, uint f) const;
//int findClosestMipmap(const InputOptions::Private & inputOptions, uint w, uint h, uint d, uint f) const;
//void downsampleMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions) const;
//void scaleMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions, uint w, uint h, uint d) const;
//void premultiplyAlphaMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions) const;
//void processInputImage(Mipmap & mipmap, const InputOptions::Private & inputOptions) const;
//void quantizeMipmap(Mipmap & mipmap, const CompressionOptions::Private & compressionOptions) const;
public:
bool cudaSupported;
bool cudaEnabled;

@ -102,11 +102,6 @@ void InputOptions::reset()
m.inputGamma = 2.2f;
m.outputGamma = 2.2f;
m.colorTransform = ColorTransform_None;
m.linearTransform = Matrix(identity);
for (int i = 0; i < 4; i++) m.colorOffsets[i] = 0;
for (int i = 0; i < 4; i++) m.swizzleTransform[i] = i;
m.generateMipmaps = true;
m.maxLevel = -1;
m.mipmapFilter = MipmapFilter_Box;
@ -123,8 +118,6 @@ void InputOptions::reset()
m.maxExtent = 0;
m.roundMode = RoundMode_None;
m.premultiplyAlpha = false;
}
@ -145,15 +138,19 @@ void InputOptions::setTextureLayout(TextureType type, int width, int height, int
resetTextureLayout();
m.textureType = type;
m.width = width;
m.height = height;
m.depth = depth;
// Allocate images.
m.faceCount = (type == TextureType_2D) ? 1 : 6;
m.mipmapCount = countMipmaps(width, height, depth);
m.faceCount = (type == TextureType_Cube) ? 6 : 1;
m.imageCount = m.mipmapCount * m.faceCount;
m.images = new void *[m.imageCount];
m.images = new Private::InputImage[m.imageCount];
memset(m.images, 0, sizeof(void *) * m.imageCount);
for(uint f = 0; f < m.faceCount; f++)
/*for (uint f = 0; f < m.faceCount; f++)
{
uint w = width;
uint h = height;
@ -175,7 +172,7 @@ void InputOptions::setTextureLayout(TextureType type, int width, int height, int
h = max(1U, h / 2);
d = max(1U, d / 2);
}
}
}*/
}
@ -197,121 +194,59 @@ void InputOptions::resetTextureLayout()
// Copies the data to our internal structures.
bool InputOptions::setMipmapData(const void * data, int width, int height, int depth /*= 1*/, int face /*= 0*/, int mipLevel /*= 0*/)
{
nvCheck(depth == 1);
const int idx = face * m.mipmapCount + mipLevel;
if (m.images[idx].width != width || m.images[idx].height != height || m.images[idx].depth != depth || m.images[idx].mipLevel != mipLevel || m.images[idx].face != face)
{
// Invalid dimension or index.
if (depth != 1) {
return false;
}
switch(m.inputFormat)
{
case InputFormat_BGRA_8UB:
if (Image * image = new nv::Image())
{
image->allocate(width, height);
memcpy(image->pixels(), data, width * height * 4);
m.images[idx].uint8data = image;
}
else
{
// @@ Out of memory error.
if (face >= m.faceCount) {
return false;
}
break;
case InputFormat_RGBA_32F:
if (FloatImage * image = new nv::FloatImage())
{
const float * floatData = (const float *)data;
image->allocate(4, width, height);
for (int c = 0; c < 4; c++)
{
float * channel = image->channel(c);
for (int i = 0; i < width * height; i++)
{
channel[i] = floatData[i*4 + c];
}
}
m.images[idx].floatdata = image;
}
else
{
// @@ Out of memory error.
if (mipLevel >= m.mipmapCount) {
return false;
}
break;
default:
const int idx = mipLevel * m.faceCount + face;
if (idx >= m.imageCount) {
return false;
}
return true;
}
// Copies data
bool InputOptions::setMipmapChannelData(const void * data, int channel, int width, int height, int depth /*= 1*/, int face /*= 0*/, int mipLevel /*= 0*/)
{
nvCheck(depth == 1);
nvCheck(channel >= 0 && channel < 4);
const int idx = face * m.mipmapCount + mipLevel;
if (m.images[idx].width != width || m.images[idx].height != height || m.images[idx].depth != depth || m.images[idx].mipLevel != mipLevel || m.images[idx].face != face)
{
// Invalid dimension or index.
// Compute expected width, height and depth for this mipLevel. Return false if it doesn't match.
int w = m.width;
int h = m.height;
int d = m.depth;
for (int i = 0; i < mipLevel; i++) {
w = max(1, w/2);
h = max(1, h/2);
d = max(1, d/2);
}
if (w != width || h != height || d != depth) {
return false;
}
// Allocate image if not allocated already.
int imageSize = width * height * depth * 4;
if (m.inputFormat == InputFormat_BGRA_8UB)
{
m.images[idx].floatdata = NULL;
if (m.images[idx].uint8data == NULL)
{
m.images[idx].uint8data = new Image();
m.images[idx].uint8data->allocate(width, height);
m.images[idx].uint8data->fill(Color32(0,0,0,0));
imageSize *= sizeof(uint8);
}
else if (m.inputFormat == InputFormat_RGBA_16F)
{
imageSize *= sizeof(uint16);
}
else if (m.inputFormat == InputFormat_RGBA_32F)
{
m.images[idx].uint8data = NULL;
if (m.images[idx].floatdata == NULL)
{
m.images[idx].floatdata = new FloatImage();
m.images[idx].floatdata->allocate(4, width, height);
m.images[idx].floatdata->clear();
}
imageSize *= sizeof(float);
}
else
{
m.images[idx].floatdata = NULL;
m.images[idx].uint8data = NULL;
return false;
}
// Copy channel data to image.
if (m.inputFormat == InputFormat_BGRA_8UB)
{
// @@ TODO
m.images[idx] = new uint8[imageSize];
if (m.images[idx] == NULL) {
// Out of memory.
return false;
}
else if (m.inputFormat == InputFormat_RGBA_32F)
{
const float * floatData = (const float *)data;
float * channelPtr = m.images[idx].floatdata->channel(channel);
for (int i = 0; i < width * height; i++)
{
channelPtr[i] = floatData[i];
}
}
memcpy(m.images[idx], data, imageSize);
return true;
}
@ -400,45 +335,6 @@ void InputOptions::setNormalizeMipmaps(bool normalize)
m.normalizeMipmaps = normalize;
}
/// Set color transform.
void InputOptions::setColorTransform(ColorTransform t)
{
m.colorTransform = t;
}
// Set linear transform for the given channel.
void InputOptions::setLinearTransform(int channel, float w0, float w1, float w2, float w3)
{
nvCheck(channel >= 0 && channel < 4);
m.linearTransform(channel, 0) = w0;
m.linearTransform(channel, 1) = w1;
m.linearTransform(channel, 2) = w2;
m.linearTransform(channel, 3) = w3;
}
void InputOptions::setLinearTransform(int channel, float w0, float w1, float w2, float w3, float offset)
{
nvCheck(channel >= 0 && channel < 4);
setLinearTransform(channel, w0, w1, w2, w3);
m.colorOffsets[channel] = offset;
}
void InputOptions::setSwizzleTransform(int x, int y, int z, int w)
{
nvCheck(x >= 0 && x <= 6);
nvCheck(y >= 0 && y <= 6);
nvCheck(z >= 0 && z <= 6);
nvCheck(w >= 0 && w <= 6);
m.swizzleTransform[0] = x;
m.swizzleTransform[1] = y;
m.swizzleTransform[2] = z;
m.swizzleTransform[3] = w;
}
void InputOptions::setMaxExtents(int e)
{
nvDebugCheck(e > 0);
@ -449,107 +345,3 @@ void InputOptions::setRoundMode(RoundMode mode)
{
m.roundMode = mode;
}
void InputOptions::setPremultiplyAlpha(bool b)
{
m.premultiplyAlpha = b;
}
void InputOptions::Private::computeTargetExtents() const
{
nvCheck(images != NULL);
uint maxExtent = this->maxExtent;
if (roundMode != RoundMode_None)
{
// rounded max extent should never be higher than original max extent.
maxExtent = previousPowerOfTwo(maxExtent);
}
uint w = images->width;
uint h = images->height;
uint d = images->depth;
nvDebugCheck(w > 0);
nvDebugCheck(h > 0);
nvDebugCheck(d > 0);
// Scale extents without changing aspect ratio.
uint maxwhd = max(max(w, h), d);
if (maxExtent != 0 && maxwhd > maxExtent)
{
w = max((w * maxExtent) / maxwhd, 1U);
h = max((h * maxExtent) / maxwhd, 1U);
d = max((d * maxExtent) / maxwhd, 1U);
}
// Round to power of two.
if (roundMode == RoundMode_ToNextPowerOfTwo)
{
w = nextPowerOfTwo(w);
h = nextPowerOfTwo(h);
d = nextPowerOfTwo(d);
}
else if (roundMode == RoundMode_ToNearestPowerOfTwo)
{
w = nearestPowerOfTwo(w);
h = nearestPowerOfTwo(h);
d = nearestPowerOfTwo(d);
}
else if (roundMode == RoundMode_ToPreviousPowerOfTwo)
{
w = previousPowerOfTwo(w);
h = previousPowerOfTwo(h);
d = previousPowerOfTwo(d);
}
this->targetWidth = w;
this->targetHeight = h;
this->targetDepth = d;
this->targetMipmapCount = countMipmaps(w, h, d);
}
// Return real number of mipmaps, including first level.
// computeTargetExtents should have been called before.
int InputOptions::Private::realMipmapCount() const
{
int mipmapCount = targetMipmapCount;
if (!generateMipmaps) mipmapCount = 1;
else if (maxLevel != -1 && maxLevel < mipmapCount - 1) mipmapCount = maxLevel + 1;
return mipmapCount;
}
const Image * InputOptions::Private::image(uint face, uint mipmap) const
{
nvDebugCheck(face < faceCount);
nvDebugCheck(mipmap < mipmapCount);
const InputImage & image = this->images[face * mipmapCount + mipmap];
nvDebugCheck(image.face == face);
nvDebugCheck(image.mipLevel == mipmap);
return image.uint8data.ptr();
}
const Image * InputOptions::Private::image(uint idx) const
{
nvDebugCheck(idx < faceCount * mipmapCount);
const InputImage & image = this->images[idx];
return image.uint8data.ptr();
}
const FloatImage * InputOptions::Private::floatImage(uint idx) const
{
nvDebugCheck(idx < faceCount * mipmapCount);
const InputImage & image = this->images[idx];
return image.floatdata.ptr();
}

@ -43,23 +43,19 @@ namespace nvtt
InputFormat inputFormat;
AlphaMode alphaMode;
uint width;
uint height;
uint depth;
uint faceCount;
uint mipmapCount;
uint imageCount;
struct InputImage;
InputImage * images;
void ** images;
// Gamma conversion.
float inputGamma;
float outputGamma;
// Color transform.
ColorTransform colorTransform;
nv::Matrix linearTransform;
float colorOffsets[4];
uint swizzleTransform[4];
// Mipmap generation options.
bool generateMipmaps;
int maxLevel;
@ -80,42 +76,6 @@ namespace nvtt
// Adjust extents.
uint maxExtent;
RoundMode roundMode;
bool premultiplyAlpha;
// @@ These are computed in nvtt::compress, so they should be mutable or stored elsewhere...
mutable uint targetWidth;
mutable uint targetHeight;
mutable uint targetDepth;
mutable uint targetMipmapCount;
void computeTargetExtents() const;
int realMipmapCount() const;
const nv::Image * image(uint face, uint mipmap) const;
const nv::Image * image(uint idx) const;
const nv::FloatImage * floatImage(uint idx) const;
};
// Internal image structure.
struct InputOptions::Private::InputImage
{
InputImage() {}
bool hasValidData() const { return uint8data != NULL || floatdata != NULL; }
int mipLevel;
int face;
int width;
int height;
int depth;
nv::AutoPtr<nv::Image> uint8data;
nv::AutoPtr<nv::FloatImage> floatdata;
};
} // nvtt namespace

@ -54,7 +54,7 @@ namespace
return d * d;
}
static uint nearestGreen4(uint green, uint maxGreen, uint minGreen)
/*static uint nearestGreen4(uint green, uint maxGreen, uint minGreen)
{
uint bias = maxGreen + (maxGreen - minGreen) / 6;
@ -62,7 +62,7 @@ namespace
if (maxGreen - minGreen != 0) index = clamp(3 * (bias - green) / (maxGreen - minGreen), 0U, 3U);
return (index * minGreen + (3 - index) * maxGreen) / 3;
}
}*/
static int computeGreenError(const ColorBlock & rgba, const BlockDXT1 * block, int bestError = INT_MAX)
{
@ -164,7 +164,7 @@ namespace
return (index * minAlpha + (7 - index) * maxAlpha) / 7;
}
static uint computeAlphaError8(const ColorBlock & rgba, const AlphaBlockDXT5 * block, int bestError = INT_MAX)
/*static uint computeAlphaError8(const ColorBlock & rgba, const AlphaBlockDXT5 * block, int bestError = INT_MAX)
{
int totalError = 0;
@ -182,7 +182,7 @@ namespace
}
return totalError;
}
}*/
static uint computeAlphaError(const ColorBlock & rgba, const AlphaBlockDXT5 * block, int bestError = INT_MAX)
{

@ -26,6 +26,7 @@
#include "nvmath/Vector.h"
#include "nvmath/Matrix.h"
#include "nvmath/Color.h"
#include "nvmath/Half.h"
#include "nvimage/Filter.h"
#include "nvimage/ImageIO.h"
@ -104,6 +105,7 @@ namespace
TexImage::TexImage() : m(new TexImage::Private())
{
m->addRef();
}
TexImage::TexImage(const TexImage & tex) : m(tex.m)
@ -300,7 +302,7 @@ bool TexImage::save(const char * fileName) const
}
}
bool TexImage::setImage2D(nvtt::InputFormat format, int w, int h, int idx, const void * restrict data)
bool TexImage::setImage2D(nvtt::InputFormat format, int w, int h, int idx, const void * data)
{
if (idx < 0 || uint(idx) >= m->imageArray.count())
{
@ -323,10 +325,10 @@ bool TexImage::setImage2D(nvtt::InputFormat format, int w, int h, int idx, const
const int count = w * h;
float * restrict rdst = img->channel(0);
float * restrict gdst = img->channel(1);
float * restrict bdst = img->channel(2);
float * restrict adst = img->channel(3);
float * rdst = img->channel(0);
float * gdst = img->channel(1);
float * bdst = img->channel(2);
float * adst = img->channel(3);
if (format == InputFormat_BGRA_8UB)
{
@ -345,6 +347,23 @@ bool TexImage::setImage2D(nvtt::InputFormat format, int w, int h, int idx, const
return false;
}
}
else if (format == InputFormat_RGBA_16F)
{
const uint16 * src = (const uint16 *)data;
try {
for (int i = 0; i < count; i++)
{
((uint32 *)rdst)[i] = half_to_float(src[4*i+0]);
((uint32 *)gdst)[i] = half_to_float(src[4*i+1]);
((uint32 *)bdst)[i] = half_to_float(src[4*i+2]);
((uint32 *)adst)[i] = half_to_float(src[4*i+3]);
}
}
catch(...) {
return false;
}
}
else if (format == InputFormat_RGBA_32F)
{
const float * src = (const float *)data;
@ -366,7 +385,7 @@ bool TexImage::setImage2D(nvtt::InputFormat format, int w, int h, int idx, const
return true;
}
bool TexImage::setImage2D(InputFormat format, int w, int h, int idx, const void * restrict r, const void * restrict g, const void * restrict b, const void * restrict a)
bool TexImage::setImage2D(InputFormat format, int w, int h, int idx, const void * r, const void * g, const void * b, const void * a)
{
if (idx < 0 || uint(idx) >= m->imageArray.count())
{
@ -383,17 +402,17 @@ bool TexImage::setImage2D(InputFormat format, int w, int h, int idx, const void
const int count = w * h;
float * restrict rdst = img->channel(0);
float * restrict gdst = img->channel(1);
float * restrict bdst = img->channel(2);
float * restrict adst = img->channel(3);
float * rdst = img->channel(0);
float * gdst = img->channel(1);
float * bdst = img->channel(2);
float * adst = img->channel(3);
if (format == InputFormat_BGRA_8UB)
{
const uint8 * restrict rsrc = (const uint8 *)r;
const uint8 * restrict gsrc = (const uint8 *)g;
const uint8 * restrict bsrc = (const uint8 *)b;
const uint8 * restrict asrc = (const uint8 *)a;
const uint8 * rsrc = (const uint8 *)r;
const uint8 * gsrc = (const uint8 *)g;
const uint8 * bsrc = (const uint8 *)b;
const uint8 * asrc = (const uint8 *)a;
try {
for (int i = 0; i < count; i++) rdst[i] = float(rsrc[i]) / 255.0f;
@ -405,6 +424,23 @@ bool TexImage::setImage2D(InputFormat format, int w, int h, int idx, const void
return false;
}
}
else if (format == InputFormat_RGBA_16F)
{
const uint16 * rsrc = (const uint16 *)r;
const uint16 * gsrc = (const uint16 *)g;
const uint16 * bsrc = (const uint16 *)b;
const uint16 * asrc = (const uint16 *)a;
try {
for (int i = 0; i < count; i++) ((uint32 *)rdst)[i] = half_to_float(rsrc[i]);
for (int i = 0; i < count; i++) ((uint32 *)gdst)[i] = half_to_float(gsrc[i]);
for (int i = 0; i < count; i++) ((uint32 *)bdst)[i] = half_to_float(bsrc[i]);
for (int i = 0; i < count; i++) ((uint32 *)adst)[i] = half_to_float(asrc[i]);
}
catch(...) {
return false;
}
}
else if (format == InputFormat_RGBA_32F)
{
const float * rsrc = (const float *)r;
@ -526,9 +562,38 @@ bool TexImage::setImage2D(Format format, Decoder decoder, int w, int h, int idx,
}
#pragma NV_MESSAGE("TODO: provide a TexImage::resize that can override filter width and parameters.")
static void getDefaultFilterWidthAndParams(int filter, float * filterWidth, float params[2])
{
if (filter == ResizeFilter_Box) {
*filterWidth = 0.5f;
}
else if (filter == ResizeFilter_Triangle) {
*filterWidth = 1.0f;
}
else if (filter == ResizeFilter_Kaiser)
{
*filterWidth = 3.0f;
params[0] = 4.0f;
params[1] = 1.0f;
}
else //if (filter == ResizeFilter_Mitchell)
{
*filterWidth = 2.0f;
params[0] = 1.0f / 3.0f;
params[1] = 1.0f / 3.0f;
}
}
void TexImage::resize(int w, int h, ResizeFilter filter)
{
float filterWidth;
float params[2];
getDefaultFilterWidthAndParams(filter, &filterWidth, params);
resize(w, h, filter, filterWidth, params);
}
void TexImage::resize(int w, int h, ResizeFilter filter, float filterWidth, const float * params)
{
if (m->imageArray.count() > 0)
{
@ -555,25 +620,25 @@ void TexImage::resize(int w, int h, ResizeFilter filter)
{
if (filter == ResizeFilter_Box)
{
BoxFilter filter;
BoxFilter filter(filterWidth);
img = img->resize(filter, w, h, wrapMode, 3);
}
else if (filter == ResizeFilter_Triangle)
{
TriangleFilter filter;
TriangleFilter filter(filterWidth);
img = img->resize(filter, w, h, wrapMode, 3);
}
else if (filter == ResizeFilter_Kaiser)
{
//KaiserFilter filter(inputOptions.kaiserWidth);
//filter.setParameters(inputOptions.kaiserAlpha, inputOptions.kaiserStretch);
KaiserFilter filter(3);
KaiserFilter filter(filterWidth);
if (params != NULL) filter.setParameters(params[0], params[1]);
img = img->resize(filter, w, h, wrapMode, 3);
}
else //if (filter == ResizeFilter_Mitchell)
{
nvDebugCheck(filter == ResizeFilter_Mitchell);
MitchellFilter filter;
if (params != NULL) filter.setParameters(params[0], params[1]);
img = img->resize(filter, w, h, wrapMode, 3);
}
}
@ -581,25 +646,25 @@ void TexImage::resize(int w, int h, ResizeFilter filter)
{
if (filter == ResizeFilter_Box)
{
BoxFilter filter;
BoxFilter filter(filterWidth);
img = img->resize(filter, w, h, wrapMode);
}
else if (filter == ResizeFilter_Triangle)
{
TriangleFilter filter;
TriangleFilter filter(filterWidth);
img = img->resize(filter, w, h, wrapMode);
}
else if (filter == ResizeFilter_Kaiser)
{
//KaiserFilter filter(inputOptions.kaiserWidth);
//filter.setParameters(inputOptions.kaiserAlpha, inputOptions.kaiserStretch);
KaiserFilter filter(3);
KaiserFilter filter(filterWidth);
if (params != NULL) filter.setParameters(params[0], params[1]);
img = img->resize(filter, w, h, wrapMode);
}
else //if (filter == ResizeFilter_Mitchell)
{
nvDebugCheck(filter == ResizeFilter_Mitchell);
MitchellFilter filter;
if (params != NULL) filter.setParameters(params[0], params[1]);
img = img->resize(filter, w, h, wrapMode);
}
}
@ -610,6 +675,16 @@ void TexImage::resize(int w, int h, ResizeFilter filter)
}
void TexImage::resize(int maxExtent, RoundMode roundMode, ResizeFilter filter)
{
float filterWidth;
float params[2];
getDefaultFilterWidthAndParams(filter, &filterWidth, params);
resize(maxExtent, roundMode, filter, filterWidth, params);
}
void TexImage::resize(int maxExtent, RoundMode roundMode, ResizeFilter filter, float filterWidth, const float * params)
{
if (m->imageArray.count() > 0)
{
@ -619,7 +694,7 @@ void TexImage::resize(int maxExtent, RoundMode roundMode, ResizeFilter filter)
nvDebugCheck(w > 0);
nvDebugCheck(h > 0);
if (roundMode != RoundMode_None)
if (roundMode != RoundMode_None && maxExtent > 0)
{
// rounded max extent should never be higher than original max extent.
maxExtent = previousPowerOfTwo(maxExtent);
@ -627,7 +702,7 @@ void TexImage::resize(int maxExtent, RoundMode roundMode, ResizeFilter filter)
// Scale extents without changing aspect ratio.
int maxwh = max(w, h);
if (maxExtent != 0 && maxwh > maxExtent)
if (maxExtent > 0 && maxwh > maxExtent)
{
w = max((w * maxExtent) / maxwh, 1);
h = max((h * maxExtent) / maxwh, 1);
@ -656,11 +731,20 @@ void TexImage::resize(int maxExtent, RoundMode roundMode, ResizeFilter filter)
w = h = max(w, h);
}
resize(w, h, filter);
resize(w, h, filter, filterWidth, params);
}
}
bool TexImage::buildNextMipmap(MipmapFilter filter)
{
float filterWidth;
float params[2];
getDefaultFilterWidthAndParams(filter, &filterWidth, params);
buildNextMipmap(filter, filterWidth, params);
}
bool TexImage::buildNextMipmap(MipmapFilter filter, float filterWidth, const float * params)
{
if (m->imageArray.count() > 0)
{
@ -690,20 +774,19 @@ bool TexImage::buildNextMipmap(MipmapFilter filter)
{
if (filter == MipmapFilter_Box)
{
BoxFilter filter;
BoxFilter filter(filterWidth);
img = img->downSample(filter, wrapMode, 3);
}
else if (filter == MipmapFilter_Triangle)
{
TriangleFilter filter;
TriangleFilter filter(filterWidth);
img = img->downSample(filter, wrapMode, 3);
}
else if (filter == MipmapFilter_Kaiser)
{
nvDebugCheck(filter == MipmapFilter_Kaiser);
//KaiserFilter filter(inputOptions.kaiserWidth);
//filter.setParameters(inputOptions.kaiserAlpha, inputOptions.kaiserStretch);
KaiserFilter filter(3);
KaiserFilter filter(filterWidth);
if (params != NULL) filter.setParameters(params[0], params[1]);
img = img->downSample(filter, wrapMode, 3);
}
}
@ -711,19 +794,24 @@ bool TexImage::buildNextMipmap(MipmapFilter filter)
{
if (filter == MipmapFilter_Box)
{
if (filterWidth == 0.5f) {
img = img->fastDownSample();
}
else {
BoxFilter filter(filterWidth);
img = img->downSample(filter, wrapMode);
}
}
else if (filter == MipmapFilter_Triangle)
{
TriangleFilter filter;
TriangleFilter filter(filterWidth);
img = img->downSample(filter, wrapMode);
}
else //if (filter == MipmapFilter_Kaiser)
{
nvDebugCheck(filter == MipmapFilter_Kaiser);
//KaiserFilter filter(inputOptions.kaiserWidth);
//filter.setParameters(inputOptions.kaiserAlpha, inputOptions.kaiserStretch);
KaiserFilter filter(3);
KaiserFilter filter(filterWidth);
if (params != NULL) filter.setParameters(params[0], params[1]);
img = img->downSample(filter, wrapMode);
}
}
@ -848,10 +936,10 @@ void TexImage::blend(float red, float green, float blue, float alpha, float t)
FloatImage * img = m->imageArray[i];
if (img == NULL) continue;
float * restrict r = img->channel(0);
float * restrict g = img->channel(1);
float * restrict b = img->channel(2);
float * restrict a = img->channel(3);
float * r = img->channel(0);
float * g = img->channel(1);
float * b = img->channel(2);
float * a = img->channel(3);
const int count = img->width() * img->height();
for (int i = 0; i < count; i++)
@ -873,10 +961,10 @@ void TexImage::premultiplyAlpha()
FloatImage * img = m->imageArray[i];
if (img == NULL) continue;
float * restrict r = img->channel(0);
float * restrict g = img->channel(1);
float * restrict b = img->channel(2);
float * restrict a = img->channel(3);
float * r = img->channel(0);
float * g = img->channel(1);
float * b = img->channel(2);
float * a = img->channel(3);
const int count = img->width() * img->height();
for (int i = 0; i < count; i++)
@ -904,10 +992,10 @@ void TexImage::toGreyScale(float redScale, float greenScale, float blueScale, fl
blueScale /= sum;
alphaScale /= sum;
float * restrict r = img->channel(0);
float * restrict g = img->channel(1);
float * restrict b = img->channel(2);
float * restrict a = img->channel(3);
float * r = img->channel(0);
float * g = img->channel(1);
float * b = img->channel(2);
float * a = img->channel(3);
const int count = img->width() * img->height();
for (int i = 0; i < count; i++)
@ -1047,6 +1135,139 @@ bool TexImage::normalizeRange(float * rangeMin, float * rangeMax)
return true;
}
// Ideally you should compress/quantize the RGB and M portions independently.
// Once you have M quantized, you would compute the corresponding RGB and quantize that.
void TexImage::toRGBM(float range/*= 1*/, float threshold/*= 0.25*/)
{
detach();
float irange = 1.0f / range;
foreach (idx, m->imageArray) {
FloatImage * img = m->imageArray[idx];
if (img == NULL) continue;
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 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 m = max(max(ri, gi), max(bi, 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;
}
}
}
// Y is in the [0, 1] range, while CoCg are in the [-1, 1] range.
void TexImage::toYCoCg()
{
detach();
foreach (idx, m->imageArray) {
FloatImage * img = m->imageArray[idx];
if (img == NULL) continue;
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 ri = r[i];
float gi = g[i];
float bi = b[i];
float Y = (2*gi + ri + bi) * 0.25f;
float Co = (ri - bi);
float Cg = (2*gi - ri - bi) * 0.5f;
r[i] = Co;
g[i] = Cg;
b[i] = 0.0f;
a[i] = Y;
}
}
}
// img.toYCoCg();
// img.blockScaleCoCg();
// img.scaleBias(0, 0.5, 0.5);
// img.scaleBias(1, 0.5, 0.5);
// @@ Add support for threshold.
// We could do something to prevent scale values from adjacent blocks from being too different to each other
// and minimize bilinear interpolation artifacts.
void TexImage::blockScaleCoCg(int bits/*= 5*/, float threshold/*= 0.0*/)
{
detach();
foreach (idx, m->imageArray) {
FloatImage * img = m->imageArray[idx];
if (img == NULL) continue;
const uint w = img->width();
const uint h = img->height();
const uint bw = max(1U, w/4);
const uint bh = max(1U, h/4);
for (uint bj = 0; bj < bh; bj++) {
for (uint bi = 0; bi < bw; bi++) {
// Compute per block scale.
float m = 1.0f / 256.0f;
for (uint j = 0; j < 4; j++) {
for (uint i = 0; i < 4; i++) {
uint x = min(bi*4 + i, w);
uint y = min(bj*4 + j, h);
float Co = img->pixel(x, y, 0);
float Cg = img->pixel(x, y, 1);
m = max(m, fabsf(Co));
m = max(m, fabsf(Cg));
}
}
float scale = quantizeCeil(m, bits);
nvDebugCheck(scale >= m);
// Store block scale in blue channel and scale CoCg.
for (uint j = 0; j < 4; j++) {
for (uint i = 0; i < 4; i++) {
uint x = min(bi*4 + i, w);
uint y = min(bj*4 + j, h);
float & Co = img->pixel(x, y, 0);
float & Cg = img->pixel(x, y, 1);
Co /= scale;
nvDebugCheck(fabsf(Co) <= 1.0f);
Cg /= scale;
nvDebugCheck(fabsf(Cg) <= 1.0f);
img->pixel(x, y, 2) = scale;
}
}
}
}
}
}
// Set normal map options.
void TexImage::toNormalMap(float sm, float medium, float big, float large)
@ -1071,20 +1292,6 @@ void TexImage::toNormalMap(float sm, float medium, float big, float large)
m->isNormalMap = true;
}
/*void TexImage::toHeightMap()
{
detach();
foreach (i, m->imageArray)
{
if (m->imageArray[i] == NULL) continue;
#pragma message(NV_FILE_LINE "TODO: Implement TexImage::toHeightMap")
}
m->isNormalMap = false;
}*/
void TexImage::normalizeNormalMap()
{
//nvCheck(m->isNormalMap);

@ -42,6 +42,8 @@ namespace nvtt
public:
Private()
{
nvDebugCheck( refCount() == 0 );
type = TextureType_2D;
wrapMode = WrapMode_Mirror;
alphaMode = AlphaMode_None;
@ -49,8 +51,10 @@ namespace nvtt
imageArray.resize(1, NULL);
}
Private(const Private & p) // Copy ctor. inits refcount to 0.
Private(const Private & p) : RefCounted() // Copy ctor. inits refcount to 0.
{
nvDebugCheck( refCount() == 0 );
type = p.type;
wrapMode = p.wrapMode;
alphaMode = p.alphaMode;

@ -262,7 +262,7 @@ static int clamp(double r, double low, double high)
// match the tonemapping function used by exrdisplay
static void tonemap(const Vector3 &in, double exposure, Vector3 &out)
/*static void tonemap(const Vector3 &in, double exposure, Vector3 &out)
{
double r,g,b;
unsigned short h;
@ -325,7 +325,7 @@ static void tonemap(const Vector3 &in, double exposure, Vector3 &out)
out.x = clamp (r, 0, 255);
out.y = clamp (g, 0, 255);
out.z = clamp (b, 0, 255);
}
}*/
static void mpsnrmap(const Vector3 &in, int exposure, Vector3 &out)
{

@ -124,38 +124,45 @@ CudaCompressor::CudaCompressor(CudaContext & ctx) : m_ctx(ctx)
}
void CudaCompressor::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, const void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
void CudaCompressor::compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions)
{
nvDebugCheck(cuda::isHardwarePresent());
#if defined HAVE_CUDA
// Allocate image as a cuda array.
const uint count = w * h;
Color32 * tmp = malloc<Color32>(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;
}
cudaArray * d_image;
if (inputFormat == nvtt::InputFormat_BGRA_8UB)
{
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc(8, 8, 8, 8, cudaChannelFormatKindUnsigned);
cudaMallocArray(&d_image, &channelDesc, w, h);
const int imageSize = w * h * sizeof(uint);
cudaMemcpyToArray(d_image, 0, 0, data, imageSize, cudaMemcpyHostToDevice);
}
else
{
#pragma NV_MESSAGE("FIXME: Floating point textures not really supported by CUDA compressors.") // @@ What's missing???
cudaMemcpyToArray(d_image, 0, 0, tmp, count * sizeof(Color32), cudaMemcpyHostToDevice);
free(tmp);
// To avoid the copy we could keep the data in floating point format, but the channels are not interleaved like the kernel expects.
/*
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc(32, 32, 32, 32, cudaChannelFormatKindFloat);
cudaMallocArray(&d_image, &channelDesc, w, h);
const int imageSize = w * h * sizeof(uint);
const int imageSize = w * h * sizeof(float) * 4;
cudaMemcpyToArray(d_image, 0, 0, data, imageSize, cudaMemcpyHostToDevice);
}
*/
// Image size in blocks.
const uint bw = (w + 3) / 4;
const uint bh = (h + 3) / 4;
const uint bs = blockSize();
const uint blockNum = bw * bh;
const uint compressedSize = blockNum * bs;
//const uint compressedSize = blockNum * bs;
void * h_result = ::malloc(min(blockNum, MAX_BLOCKS) * bs);
@ -194,7 +201,6 @@ void CudaCompressor::compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alp
#else
outputOptions.error(Error_CudaError);
#endif
}
#if defined HAVE_CUDA

@ -53,7 +53,7 @@ namespace nv
{
CudaCompressor(CudaContext & ctx);
virtual void compress(nvtt::InputFormat inputFormat, nvtt::AlphaMode alphaMode, uint w, uint h, const void * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
virtual void compress(nvtt::AlphaMode alphaMode, uint w, uint h, const float * data, const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions);
virtual void setup(cudaArray * image, const nvtt::CompressionOptions::Private & compressionOptions) = 0;
virtual void compressBlocks(uint first, uint count, uint w, uint h, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output) = 0;

@ -91,9 +91,8 @@ namespace nvtt
Format_BC4, // ATI1
Format_BC5, // 3DC, ATI2
Format_DXT1n,// Not supported on CPU yet.
Format_DXT1n, // Not supported on CPU yet.
Format_CTX1, // Not supported on CPU yet.
//Format_YCoCg_DXT5, // Not supported yet.
Format_BC6, // Not supported yet.
Format_BC7, // Not supported yet.
@ -104,12 +103,12 @@ namespace nvtt
/// Pixel types. These basically indicate how the output should be interpreted, but do not have any influence over the input.
enum PixelType
{
PixelType_UnsignedNorm,
PixelType_SignedNorm, // Not supported yet.
PixelType_UnsignedInt, // Not supported yet.
PixelType_SignedInt, // Not supported yet.
PixelType_Float,
PixelType_UnsignedFloat,
PixelType_UnsignedNorm = 0,
PixelType_SignedNorm = 1, // Not supported yet.
PixelType_UnsignedInt = 2, // Not supported yet.
PixelType_SignedInt = 3, // Not supported yet.
PixelType_Float = 4,
PixelType_UnsignedFloat = 5,
};
/// Quality modes.
@ -179,8 +178,9 @@ namespace nvtt
/// Input formats.
enum InputFormat
{
InputFormat_BGRA_8UB,
InputFormat_RGBA_32F,
InputFormat_BGRA_8UB, // Normalized [0, 1] 8 bit fixed point.
InputFormat_RGBA_16F, // 16 bit floating point.
InputFormat_RGBA_32F, // 32 bit floating point.
};
/// Mipmap downsampling filters.
@ -200,16 +200,6 @@ namespace nvtt
ResizeFilter_Mitchell,
};
/// Color transformation.
enum ColorTransform
{
ColorTransform_None,
ColorTransform_Linear, ///< Not implemented.
ColorTransform_Swizzle, ///< Not implemented.
ColorTransform_YCoCg, ///< Transform into r=Co, g=Cg, b=0, a=Y
ColorTransform_ScaledYCoCg, ///< Not implemented.
};
/// Extents rounding mode.
enum RoundMode
{
@ -245,7 +235,6 @@ namespace nvtt
// Set mipmap data. Copies the data.
NVTT_API bool setMipmapData(const void * data, int w, int h, int d = 1, int face = 0, int mipmap = 0);
NVTT_API bool setMipmapChannelData(const void * data, int channel, int w, int h, int d = 1, int face = 0, int mipmap = 0);
// Describe the format of the input.
NVTT_API void setFormat(InputFormat format);
@ -271,18 +260,9 @@ namespace nvtt
NVTT_API void setNormalFilter(float sm, float medium, float big, float large);
NVTT_API void setNormalizeMipmaps(bool b);
// Set color transforms.
NVTT_API void setColorTransform(ColorTransform t);
NVTT_API void setLinearTransform(int channel, float w0, float w1, float w2, float w3);
NVTT_API void setLinearTransform(int channel, float w0, float w1, float w2, float w3, float offset);
NVTT_API void setSwizzleTransform(int x, int y, int z, int w);
// Set resizing options.
NVTT_API void setMaxExtents(int d);
NVTT_API void setRoundMode(RoundMode mode);
// Set whether or not to premultiply color by alpha
NVTT_API void setPremultiplyAlpha(bool b);
};
@ -364,20 +344,18 @@ namespace nvtt
NVTT_API void enableCudaAcceleration(bool enable);
NVTT_API bool isCudaAccelerationEnabled() const;
// InputOptions api.
// InputOptions API.
NVTT_API bool process(const InputOptions & inputOptions, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const;
NVTT_API int estimateSize(const InputOptions & inputOptions, const CompressionOptions & compressionOptions) const;
// RAW api.
NVTT_API bool compress2D(InputFormat format, int w, int h, void * data, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const;
//ßNVTT_API bool compress3D(InputFormat format, int w, int h, int d, void * data, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const;
NVTT_API int estimateSize(int w, int h, int d, const CompressionOptions & compressionOptions) const;
// TexImage api.
NVTT_API TexImage createTexImage() const;
// 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 int estimateSize(const TexImage & tex, const CompressionOptions & compressionOptions) 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 int estimateSize(int w, int h, int d, int mipmapCount, const CompressionOptions & compressionOptions) const;
};
// "Compressor" is deprecated. This should have been called "Context"
@ -394,6 +372,7 @@ namespace nvtt
/// A texture mipmap.
struct TexImage
{
NVTT_API TexImage();
NVTT_API TexImage(const TexImage & tex);
NVTT_API ~TexImage();
@ -426,8 +405,11 @@ namespace nvtt
// Resizing methods.
NVTT_API void resize(int w, int h, ResizeFilter filter);
NVTT_API void resize(int w, int h, ResizeFilter filter, float filterWidth, const float * params = 0);
NVTT_API void resize(int maxExtent, RoundMode mode, ResizeFilter filter);
NVTT_API void resize(int maxExtent, RoundMode mode, ResizeFilter filter, float filterWidth, const float * params = 0);
NVTT_API bool buildNextMipmap(MipmapFilter filter);
NVTT_API bool buildNextMipmap(MipmapFilter filter, float filterWidth, const float * params = 0);
// Color transforms.
NVTT_API void toLinear(float gamma);
@ -445,10 +427,14 @@ namespace nvtt
NVTT_API void fill(float r, float g, float b, float a);
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 toYCoCg();
NVTT_API void blockScaleCoCg(int bits = 5, float threshold = 0.0f);
// @@ Add quantization methods.
// Set normal map options.
NVTT_API void toNormalMap(float sm, float medium, float big, float large);
//NVTT_API void toHeightMap();
NVTT_API void normalizeNormalMap();
// Error compare.
@ -463,10 +449,9 @@ namespace nvtt
NVTT_API bool copyChannel(const TexImage & srcImage, int srcChannel, int dstChannel);
private:
TexImage();
void detach();
friend struct Compressor::Private;
friend struct Compressor;
struct Private;
Private * m;
};
@ -478,10 +463,6 @@ namespace nvtt
// Return NVTT version.
NVTT_API unsigned int version();
// Set callbacks.
//NVTT_API void setErrorCallback(ErrorCallback callback);
//NVTT_API void setMemoryCallbacks(...);
} // nvtt namespace
#endif // NVTT_H

@ -89,16 +89,6 @@ void nvttSetInputOptionsNormalizeMipmaps(NvttInputOptions * inputOptions, NvttBo
inputOptions->setNormalizeMipmaps(b != NVTT_False);
}
void nvttSetInputOptionsColorTransform(NvttInputOptions * inputOptions, NvttColorTransform t)
{
inputOptions->setColorTransform((nvtt::ColorTransform)t);
}
void nvttSetInputOptionsLinearTransfrom(NvttInputOptions * inputOptions, int channel, float w0, float w1, float w2, float w3)
{
inputOptions->setLinearTransform(channel, w0, w1, w2, w3);
}
void nvttSetInputOptionsMaxExtents(NvttInputOptions * inputOptions, int dim)
{
inputOptions->setMaxExtents(dim);

@ -123,13 +123,6 @@ typedef enum
NVTT_MipmapFilter_Kaiser,
} NvttMipmapFilter;
/// Color transformation.
typedef enum
{
NVTT_ColorTransform_None,
NVTT_ColorTransform_Linear,
} NvttColorTransform;
/// Extents rounding mode.
typedef enum
{
@ -195,8 +188,6 @@ NVTT_API void nvttSetInputOptionsConvertToNormalMap(NvttInputOptions * inputOpti
NVTT_API void nvttSetInputOptionsHeightEvaluation(NvttInputOptions * inputOptions, float redScale, float greenScale, float blueScale, float alphaScale);
NVTT_API void nvttSetInputOptionsNormalFilter(NvttInputOptions * inputOptions, float sm, float medium, float big, float large);
NVTT_API void nvttSetInputOptionsNormalizeMipmaps(NvttInputOptions * inputOptions, NvttBoolean b);
NVTT_API void nvttSetInputOptionsColorTransform(NvttInputOptions * inputOptions, NvttColorTransform t);
NVTT_API void nvttSetInputOptionsLinearTransform(NvttInputOptions * inputOptions, int channel, float w0, float w1, float w2, float w3);
NVTT_API void nvttSetInputOptionsMaxExtents(NvttInputOptions * inputOptions, int dim);
NVTT_API void nvttSetInputOptionsRoundMode(NvttInputOptions * inputOptions, NvttRoundMode mode);

@ -38,7 +38,7 @@ int main(int argc, char *argv[])
context.enableCudaAcceleration(false);
// Load input image.
nvtt::TexImage image = context.createTexImage();
nvtt::TexImage image;
if (!image.load(inputFileName)) {
return EXIT_FAILURE;
}

@ -43,7 +43,7 @@ int main(int argc, char *argv[])
context.enableCudaAcceleration(false);
// Load color map.
nvtt::TexImage colorMap = context.createTexImage();
nvtt::TexImage colorMap;
if (!colorMap.load(inputFileNameColor)) {
printf("Image '%s' could not be loaded.\n", inputFileNameColor);
return EXIT_FAILURE;
@ -63,9 +63,8 @@ int main(int argc, char *argv[])
colorOutputOptions.setFileName(outputFileNameColor.str());
// Load normal map.
nvtt::TexImage normalMap = context.createTexImage();
nvtt::TexImage normalMap;
if (inputFileNameNormal != NULL) {
normalMap = context.createTexImage();
if (!normalMap.load(inputFileNameColor)) {
printf("Image '%s' could not be loaded.\n", inputFileNameNormal);
return EXIT_FAILURE;

@ -37,6 +37,7 @@
#include <stdlib.h> // free
#include <string.h> // memcpy
#include "../tools/cmdline.h"
using namespace nv;
@ -294,11 +295,15 @@ float rmsError(const Image * a, const Image * b)
int main(int argc, char *argv[])
{
MyAssertHandler assertHandler;
MyMessageHandler messageHandler;
const uint version = nvtt::version();
const uint major = version / 100;
const uint minor = version % 100;
const uint major = version / 100 / 100;
const uint minor = (version / 100) % 100;
const uint rev = version % 100;
printf("NVIDIA Texture Tools %u.%u - Copyright NVIDIA Corporation 2007 - 2008\n\n", major, minor);
printf("NVIDIA Texture Tools %u.%u.%u - Copyright NVIDIA Corporation 2007\n\n", major, minor, rev);
int set = 0;
bool fast = false;

@ -412,10 +412,10 @@ int main(int argc, char *argv[])
inputOptions.setFormat(nvtt::InputFormat_RGBA_32F);
inputOptions.setTextureLayout(nvtt::TextureType_2D, image->width(), image->height());
for (uint i = 0; i < image->componentNum(); i++)
/*for (uint i = 0; i < image->componentNum(); i++)
{
inputOptions.setMipmapChannelData(image->channel(i), i, image->width(), image->height());
}
}*/
}
else
{
@ -450,8 +450,11 @@ int main(int argc, char *argv[])
inputOptions.setAlphaMode(nvtt::AlphaMode_None);
}
// Block compressed textures with mipmaps must be powers of two.
//if (!noMipmaps && format != nvtt::Format_RGB)
{
inputOptions.setRoundMode(nvtt::RoundMode_ToNearestPowerOfTwo);
}
if (normal)
{
@ -471,11 +474,11 @@ int main(int argc, char *argv[])
inputOptions.setMipmapGeneration(false);
}
if (premultiplyAlpha)
/*if (premultiplyAlpha)
{
inputOptions.setPremultiplyAlpha(true);
inputOptions.setAlphaMode(nvtt::AlphaMode_Premultiplied);
}
}*/
inputOptions.setMipmapFilter(mipmapFilter);

@ -169,14 +169,14 @@ int main(int argc, char *argv[])
nv::FloatImage fimage(&image);
fimage.toLinear(0, 3, gamma);
#if 0
#if 1
nv::AutoPtr<nv::FloatImage> fresult(fimage.resize(*filter, uint(image.width() * scale), uint(image.height() * scale), wrapMode));
nv::AutoPtr<nv::Image> result(fresult->createImageGammaCorrect(gamma));
result->setFormat(nv::Image::Format_ARGB);
nv::StdOutputStream stream(output);
nv::ImageIO::save(output, stream, result.ptr());
nv::StdOutputStream stream(output.str());
nv::ImageIO::save(output.str(), stream, result.ptr());
#endif
return 0;
}

Loading…
Cancel
Save