Fix msvc warnings and errors.

Test TexImage stuff more througly.
Test YCoCg and RGBM.
pull/216/head
castano 14 years ago
parent c1204bfb66
commit 5f845513ee

@ -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

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright Ignacio Castano <icastano@nvidia.com> 2009
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,4 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,4 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2008 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2008-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// 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<CompressorInterface> 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);
}
}

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2008 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// 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;

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// 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;
}

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2008 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// 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;
}

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// 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<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;
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;

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,239 +1,240 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
//
// 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 <cuda.h>
#include <cuda_runtime_api.h>
#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 <windows.h>
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 <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// 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 <cuda.h>
#include <cuda_runtime_api.h>
#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 <windows.h>
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
}

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// 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();

@ -1,3 +1,26 @@
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// 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"

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation

@ -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;

@ -1,4 +1,5 @@
// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
//
// 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<Image> 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<Image> 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<Image> 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<Image> 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;

Loading…
Cancel
Save