Merge changes from the-witness.
Fix DXT5n compressor.
This commit is contained in:
@ -37,63 +37,62 @@ namespace nv
|
||||
public:
|
||||
|
||||
/// Ctor.
|
||||
StdStream( FILE * fp, bool autoclose=true ) :
|
||||
m_fp(fp), m_autoclose(autoclose) { }
|
||||
StdStream( FILE * fp, bool autoclose=true ) : m_fp(fp), m_autoclose(autoclose) { }
|
||||
|
||||
/// Dtor.
|
||||
virtual ~StdStream()
|
||||
{
|
||||
if( m_fp != NULL && m_autoclose ) {
|
||||
fclose( m_fp );
|
||||
}
|
||||
}
|
||||
/// Dtor.
|
||||
virtual ~StdStream()
|
||||
{
|
||||
if( m_fp != NULL && m_autoclose ) {
|
||||
_fclose_nolock( m_fp );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @name Stream implementation. */
|
||||
//@{
|
||||
virtual void seek( uint pos )
|
||||
{
|
||||
nvDebugCheck(m_fp != NULL);
|
||||
nvDebugCheck(pos < size());
|
||||
fseek(m_fp, pos, SEEK_SET);
|
||||
}
|
||||
/** @name Stream implementation. */
|
||||
//@{
|
||||
virtual void seek( uint pos )
|
||||
{
|
||||
nvDebugCheck(m_fp != NULL);
|
||||
nvDebugCheck(pos < size());
|
||||
_fseek_nolock(m_fp, pos, SEEK_SET);
|
||||
}
|
||||
|
||||
virtual uint tell() const
|
||||
{
|
||||
nvDebugCheck(m_fp != NULL);
|
||||
return ftell(m_fp);
|
||||
}
|
||||
virtual uint tell() const
|
||||
{
|
||||
nvDebugCheck(m_fp != NULL);
|
||||
return _ftell_nolock(m_fp);
|
||||
}
|
||||
|
||||
virtual uint size() const
|
||||
{
|
||||
nvDebugCheck(m_fp != NULL);
|
||||
uint pos = ftell(m_fp);
|
||||
fseek(m_fp, 0, SEEK_END);
|
||||
uint end = ftell(m_fp);
|
||||
fseek(m_fp, pos, SEEK_SET);
|
||||
return end;
|
||||
}
|
||||
virtual uint size() const
|
||||
{
|
||||
nvDebugCheck(m_fp != NULL);
|
||||
uint pos = ftell(m_fp);
|
||||
_fseek_nolock(m_fp, 0, SEEK_END);
|
||||
uint end = ftell(m_fp);
|
||||
_fseek_nolock(m_fp, pos, SEEK_SET);
|
||||
return end;
|
||||
}
|
||||
|
||||
virtual bool isError() const
|
||||
{
|
||||
return m_fp == NULL || ferror( m_fp ) != 0;
|
||||
}
|
||||
virtual bool isError() const
|
||||
{
|
||||
return m_fp == NULL || ferror( m_fp ) != 0;
|
||||
}
|
||||
|
||||
virtual void clearError()
|
||||
{
|
||||
nvDebugCheck(m_fp != NULL);
|
||||
clearerr(m_fp);
|
||||
}
|
||||
virtual void clearError()
|
||||
{
|
||||
nvDebugCheck(m_fp != NULL);
|
||||
clearerr(m_fp);
|
||||
}
|
||||
|
||||
virtual bool isAtEnd() const
|
||||
{
|
||||
nvDebugCheck(m_fp != NULL);
|
||||
return feof( m_fp ) != 0;
|
||||
}
|
||||
virtual bool isAtEnd() const
|
||||
{
|
||||
nvDebugCheck(m_fp != NULL);
|
||||
return feof( m_fp ) != 0;
|
||||
}
|
||||
|
||||
/// Always true.
|
||||
virtual bool isSeekable() const { return true; }
|
||||
//@}
|
||||
/// Always true.
|
||||
virtual bool isSeekable() const { return true; }
|
||||
//@}
|
||||
|
||||
protected:
|
||||
|
||||
@ -110,34 +109,33 @@ namespace nv
|
||||
public:
|
||||
|
||||
/// Construct stream by file name.
|
||||
StdOutputStream( const char * name ) :
|
||||
StdStream(fileOpen(name, "wb")) { }
|
||||
StdOutputStream( const char * name ) : StdStream(fileOpen(name, "wb")) { }
|
||||
|
||||
/// Construct stream by file handle.
|
||||
StdOutputStream( FILE * fp, bool autoclose=true ) : StdStream(fp, autoclose)
|
||||
{
|
||||
}
|
||||
/// Construct stream by file handle.
|
||||
StdOutputStream( FILE * fp, bool autoclose=true ) : StdStream(fp, autoclose)
|
||||
{
|
||||
}
|
||||
|
||||
/** @name Stream implementation. */
|
||||
//@{
|
||||
/// Write data.
|
||||
virtual uint serialize( void * data, uint len )
|
||||
{
|
||||
nvDebugCheck(data != NULL);
|
||||
nvDebugCheck(m_fp != NULL);
|
||||
return (uint)fwrite(data, 1, len, m_fp);
|
||||
}
|
||||
/** @name Stream implementation. */
|
||||
//@{
|
||||
/// Write data.
|
||||
virtual uint serialize( void * data, uint len )
|
||||
{
|
||||
nvDebugCheck(data != NULL);
|
||||
nvDebugCheck(m_fp != NULL);
|
||||
return (uint)_fwrite_nolock(data, 1, len, m_fp);
|
||||
}
|
||||
|
||||
virtual bool isLoading() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual bool isLoading() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool isSaving() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
//@}
|
||||
virtual bool isSaving() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
//@}
|
||||
|
||||
};
|
||||
|
||||
@ -149,34 +147,33 @@ namespace nv
|
||||
public:
|
||||
|
||||
/// Construct stream by file name.
|
||||
StdInputStream( const char * name ) :
|
||||
StdStream(fileOpen(name, "rb")) { }
|
||||
StdInputStream( const char * name ) : StdStream(fileOpen(name, "rb")) { }
|
||||
|
||||
/// Construct stream by file handle.
|
||||
StdInputStream( FILE * fp, bool autoclose=true ) : StdStream(fp, autoclose)
|
||||
{
|
||||
}
|
||||
/// Construct stream by file handle.
|
||||
StdInputStream( FILE * fp, bool autoclose=true ) : StdStream(fp, autoclose)
|
||||
{
|
||||
}
|
||||
|
||||
/** @name Stream implementation. */
|
||||
//@{
|
||||
/// Read data.
|
||||
virtual uint serialize( void * data, uint len )
|
||||
{
|
||||
nvDebugCheck(data != NULL);
|
||||
nvDebugCheck(m_fp != NULL);
|
||||
return (uint)fread(data, 1, len, m_fp);
|
||||
}
|
||||
/** @name Stream implementation. */
|
||||
//@{
|
||||
/// Read data.
|
||||
virtual uint serialize( void * data, uint len )
|
||||
{
|
||||
nvDebugCheck(data != NULL);
|
||||
nvDebugCheck(m_fp != NULL);
|
||||
return (uint)_fread_nolock(data, 1, len, m_fp);
|
||||
}
|
||||
|
||||
virtual bool isLoading() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
virtual bool isLoading() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool isSaving() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//@}
|
||||
virtual bool isSaving() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//@}
|
||||
};
|
||||
|
||||
|
||||
@ -188,75 +185,74 @@ namespace nv
|
||||
public:
|
||||
|
||||
/// Ctor.
|
||||
MemoryInputStream( const uint8 * mem, uint size ) :
|
||||
m_mem(mem), m_ptr(mem), m_size(size) { }
|
||||
MemoryInputStream( const uint8 * mem, uint size ) : m_mem(mem), m_ptr(mem), m_size(size) { }
|
||||
|
||||
/** @name Stream implementation. */
|
||||
//@{
|
||||
/// Read data.
|
||||
virtual uint serialize( void * data, uint len )
|
||||
{
|
||||
nvDebugCheck(data != NULL);
|
||||
nvDebugCheck(!isError());
|
||||
/** @name Stream implementation. */
|
||||
//@{
|
||||
/// Read data.
|
||||
virtual uint serialize( void * data, uint len )
|
||||
{
|
||||
nvDebugCheck(data != NULL);
|
||||
nvDebugCheck(!isError());
|
||||
|
||||
uint left = m_size - tell();
|
||||
if (len > left) len = left;
|
||||
uint left = m_size - tell();
|
||||
if (len > left) len = left;
|
||||
|
||||
memcpy( data, m_ptr, len );
|
||||
m_ptr += len;
|
||||
memcpy( data, m_ptr, len );
|
||||
m_ptr += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
virtual void seek( uint pos )
|
||||
{
|
||||
nvDebugCheck(!isError());
|
||||
m_ptr = m_mem + pos;
|
||||
nvDebugCheck(!isError());
|
||||
}
|
||||
virtual void seek( uint pos )
|
||||
{
|
||||
nvDebugCheck(!isError());
|
||||
m_ptr = m_mem + pos;
|
||||
nvDebugCheck(!isError());
|
||||
}
|
||||
|
||||
virtual uint tell() const
|
||||
{
|
||||
nvDebugCheck(m_ptr >= m_mem);
|
||||
return uint(m_ptr - m_mem);
|
||||
}
|
||||
virtual uint tell() const
|
||||
{
|
||||
nvDebugCheck(m_ptr >= m_mem);
|
||||
return uint(m_ptr - m_mem);
|
||||
}
|
||||
|
||||
virtual uint size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
virtual uint size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
virtual bool isError() const
|
||||
{
|
||||
return m_mem == NULL || m_ptr > m_mem + m_size || m_ptr < m_mem;
|
||||
}
|
||||
virtual bool isError() const
|
||||
{
|
||||
return m_mem == NULL || m_ptr > m_mem + m_size || m_ptr < m_mem;
|
||||
}
|
||||
|
||||
virtual void clearError()
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
virtual void clearError()
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
virtual bool isAtEnd() const
|
||||
{
|
||||
return m_ptr == m_mem + m_size;
|
||||
}
|
||||
virtual bool isAtEnd() const
|
||||
{
|
||||
return m_ptr == m_mem + m_size;
|
||||
}
|
||||
|
||||
/// Always true.
|
||||
virtual bool isSeekable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
/// Always true.
|
||||
virtual bool isSeekable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool isLoading() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
virtual bool isLoading() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool isSaving() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//@}
|
||||
virtual bool isSaving() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//@}
|
||||
|
||||
|
||||
private:
|
||||
|
@ -426,6 +426,21 @@ StringBuilder & StringBuilder::copy( const StringBuilder & s )
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool StringBuilder::endsWith(const char * str) const
|
||||
{
|
||||
size_t l = strlen(str);
|
||||
size_t ml = strlen(m_str);
|
||||
if (ml < l) return false;
|
||||
return strncmp(m_str + ml - l, str, l) == 0;
|
||||
}
|
||||
|
||||
bool StringBuilder::beginsWith(const char * str) const
|
||||
{
|
||||
size_t l = strlen(str);
|
||||
return strncmp(m_str, str, l) == 0;
|
||||
}
|
||||
|
||||
|
||||
/** Reset the string. */
|
||||
void StringBuilder::reset()
|
||||
{
|
||||
|
@ -82,6 +82,9 @@ namespace nv
|
||||
StringBuilder & toLower();
|
||||
StringBuilder & toUpper();
|
||||
|
||||
bool endsWith(const char * str) const;
|
||||
bool beginsWith(const char * str) const;
|
||||
|
||||
void reset();
|
||||
bool isNull() const { return m_size == 0; }
|
||||
|
||||
|
@ -10,20 +10,24 @@
|
||||
|
||||
#include <time.h> //clock
|
||||
|
||||
class NVCORE_CLASS Timer
|
||||
{
|
||||
public:
|
||||
Timer() {}
|
||||
namespace nv {
|
||||
|
||||
void start() { m_start = clock(); }
|
||||
void stop() { m_stop = clock(); }
|
||||
class NVCORE_CLASS Timer
|
||||
{
|
||||
public:
|
||||
Timer() {}
|
||||
|
||||
float elapsed() const { return float(m_stop - m_start) / CLOCKS_PER_SEC; }
|
||||
void start() { m_start = clock(); }
|
||||
void stop() { m_stop = clock(); }
|
||||
|
||||
private:
|
||||
clock_t m_start;
|
||||
clock_t m_stop;
|
||||
};
|
||||
float elapsed() const { return float(m_stop - m_start) / CLOCKS_PER_SEC; }
|
||||
|
||||
private:
|
||||
clock_t m_start;
|
||||
clock_t m_stop;
|
||||
};
|
||||
|
||||
} // nv namespace
|
||||
|
||||
#else
|
||||
|
||||
|
@ -141,9 +141,8 @@ void ColorBlock::swizzle(uint x, uint y, uint z, uint w)
|
||||
|
||||
|
||||
/// Returns true if the block has a single color.
|
||||
bool ColorBlock::isSingleColor() const
|
||||
bool ColorBlock::isSingleColor(Color32 mask/*= Color32(0xFF, 0xFF, 0xFF, 0x00)*/) const
|
||||
{
|
||||
Color32 mask(0xFF, 0xFF, 0xFF, 0x00);
|
||||
uint u = m_color[0].u & mask.u;
|
||||
|
||||
for (int i = 1; i < 16; i++)
|
||||
@ -184,7 +183,7 @@ bool ColorBlock::isSingleColorNoAlpha() const
|
||||
*/
|
||||
|
||||
/// Count number of unique colors in this color block.
|
||||
uint ColorBlock::countUniqueColors() const
|
||||
/*uint ColorBlock::countUniqueColors() const
|
||||
{
|
||||
uint count = 0;
|
||||
|
||||
@ -204,7 +203,7 @@ uint ColorBlock::countUniqueColors() const
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}*/
|
||||
|
||||
/*/// Get average color of the block.
|
||||
Color32 ColorBlock::averageColor() const
|
||||
|
@ -25,9 +25,8 @@ namespace nv
|
||||
|
||||
void swizzle(uint x, uint y, uint z, uint w); // 0=r, 1=g, 2=b, 3=a, 4=0xFF, 5=0
|
||||
|
||||
bool isSingleColor() const;
|
||||
//bool isSingleColorNoAlpha() const;
|
||||
uint countUniqueColors() const;
|
||||
bool isSingleColor(Color32 mask = Color32(0xFF, 0xFF, 0xFF, 0x00)) const;
|
||||
//uint countUniqueColors() const;
|
||||
//Color32 averageColor() const;
|
||||
bool hasAlpha() const;
|
||||
|
||||
|
0
src/nvmath/Box.cpp
Executable file → Normal file
0
src/nvmath/Box.cpp
Executable file → Normal file
@ -221,10 +221,38 @@ void NormalCompressorDXT5::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alph
|
||||
|
||||
void NormalCompressorDXT5n::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alphaMode, const nvtt::CompressionOptions::Private & compressionOptions, void * output)
|
||||
{
|
||||
rgba.swizzle(4, 1, 5, 0); // 0xFF, G, 0, R
|
||||
|
||||
BlockDXT5 * block = new(output) BlockDXT5;
|
||||
|
||||
// Compress Y.
|
||||
if (compressionOptions.quality == Quality_Highest)
|
||||
{
|
||||
OptimalCompress::compressDXT1G(rgba, &block->color);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rgba.isSingleColor(Color32(0, 0xFF, 0, 0))) // Mask all but green channel.
|
||||
{
|
||||
OptimalCompress::compressDXT1G(rgba.color(0).g, &block->color);
|
||||
}
|
||||
else
|
||||
{
|
||||
ColorBlock tile = rgba;
|
||||
tile.swizzle(4, 1, 5, 3); // leave alpha in alpha channel.
|
||||
|
||||
nvsquish::WeightedClusterFit fit;
|
||||
fit.SetMetric(0, 1, 0);
|
||||
|
||||
int flags = 0;
|
||||
if (alphaMode == nvtt::AlphaMode_Transparency) flags |= nvsquish::kWeightColourByAlpha;
|
||||
|
||||
nvsquish::ColourSet colours((uint8 *)tile.colors(), flags);
|
||||
fit.SetColourSet(&colours, 0);
|
||||
fit.Compress(&block->color);
|
||||
}
|
||||
}
|
||||
|
||||
rgba.swizzle(4, 1, 5, 0); // 1, G, 0, R
|
||||
|
||||
// Compress X.
|
||||
if (compressionOptions.quality == Quality_Highest)
|
||||
{
|
||||
@ -234,31 +262,6 @@ void NormalCompressorDXT5n::compressBlock(ColorBlock & rgba, nvtt::AlphaMode alp
|
||||
{
|
||||
QuickCompress::compressDXT5A(rgba, &block->alpha);
|
||||
}
|
||||
|
||||
// Compress Y.
|
||||
if (compressionOptions.quality == Quality_Highest)
|
||||
{
|
||||
OptimalCompress::compressDXT1G(rgba, &block->color);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rgba.isSingleColor())
|
||||
{
|
||||
OptimalCompress::compressDXT1G(rgba.color(0), &block->color);
|
||||
}
|
||||
else
|
||||
{
|
||||
nvsquish::WeightedClusterFit fit;
|
||||
fit.SetMetric(0, 1, 0);
|
||||
|
||||
int flags = 0;
|
||||
if (alphaMode == nvtt::AlphaMode_Transparency) flags |= nvsquish::kWeightColourByAlpha;
|
||||
|
||||
nvsquish::ColourSet colours((uint8 *)rgba.colors(), flags);
|
||||
fit.SetColourSet(&colours, 0);
|
||||
fit.Compress(&block->color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -312,13 +312,19 @@ bool TexImage::setImage2D(nvtt::InputFormat format, int w, int h, int idx, const
|
||||
}
|
||||
|
||||
FloatImage * img = m->imageArray[idx];
|
||||
if (img->width() != w || img->height() != h)
|
||||
{
|
||||
return false;
|
||||
if (img != NULL) {
|
||||
if (img->width() != w || img->height() != h) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
detach();
|
||||
|
||||
if (img == NULL) {
|
||||
img = m->imageArray[idx] = new FloatImage();
|
||||
img->allocate(4, w, h);
|
||||
}
|
||||
|
||||
const int count = w * h;
|
||||
|
||||
float * restrict rdst = img->channel(0);
|
||||
@ -333,10 +339,10 @@ bool TexImage::setImage2D(nvtt::InputFormat format, int w, int h, int idx, const
|
||||
try {
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
rdst[i] = src[i].r;
|
||||
gdst[i] = src[i].g;
|
||||
bdst[i] = src[i].b;
|
||||
adst[i] = src[i].a;
|
||||
rdst[i] = float(src[i].r) / 255.0f;
|
||||
gdst[i] = float(src[i].g) / 255.0f;
|
||||
bdst[i] = float(src[i].b) / 255.0f;
|
||||
adst[i] = float(src[i].a) / 255.0f;
|
||||
}
|
||||
}
|
||||
catch(...) {
|
||||
|
@ -391,7 +391,6 @@ namespace nvtt
|
||||
/// A texture mipmap.
|
||||
struct TexImage
|
||||
{
|
||||
NVTT_API TexImage();
|
||||
NVTT_API TexImage(const TexImage & tex);
|
||||
NVTT_API ~TexImage();
|
||||
|
||||
@ -459,6 +458,7 @@ namespace nvtt
|
||||
NVTT_API bool copyChannel(const TexImage & srcImage, int srcChannel, int dstChannel);
|
||||
|
||||
private:
|
||||
TexImage();
|
||||
void detach();
|
||||
|
||||
friend struct Compressor;
|
||||
|
@ -558,7 +558,7 @@ int main(int argc, char *argv[])
|
||||
// fflush(stdout);
|
||||
// getchar();
|
||||
|
||||
Timer timer;
|
||||
nv::Timer timer;
|
||||
timer.start();
|
||||
|
||||
if (!context.process(inputOptions, compressionOptions, outputOptions))
|
||||
|
Reference in New Issue
Block a user