2010-11-06 02:34:34 +00:00
|
|
|
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
|
|
|
|
// Copyright (c) 2007-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
|
2007-05-17 00:11:38 +00:00
|
|
|
//
|
|
|
|
// 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 "CompressionOptions.h"
|
2011-01-08 04:54:06 +00:00
|
|
|
#include "nvimage/DirectDrawSurface.h"
|
2012-01-04 02:25:28 +00:00
|
|
|
#include "nvmath/Vector.inl"
|
2007-05-17 00:11:38 +00:00
|
|
|
|
|
|
|
using namespace nv;
|
|
|
|
using namespace nvtt;
|
|
|
|
|
|
|
|
|
|
|
|
/// Constructor. Sets compression options to the default values.
|
|
|
|
CompressionOptions::CompressionOptions() : m(*new CompressionOptions::Private())
|
|
|
|
{
|
2010-11-03 18:53:51 +00:00
|
|
|
reset();
|
2007-05-17 00:11:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Destructor.
|
|
|
|
CompressionOptions::~CompressionOptions()
|
|
|
|
{
|
2010-11-03 18:53:51 +00:00
|
|
|
delete &m;
|
2007-05-17 00:11:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Set default compression options.
|
|
|
|
void CompressionOptions::reset()
|
|
|
|
{
|
2010-11-03 18:53:51 +00:00
|
|
|
m.format = Format_DXT1;
|
|
|
|
m.quality = Quality_Normal;
|
|
|
|
m.colorWeight.set(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
|
|
|
|
m.bitcount = 32;
|
|
|
|
m.bmask = 0x000000FF;
|
|
|
|
m.gmask = 0x0000FF00;
|
|
|
|
m.rmask = 0x00FF0000;
|
|
|
|
m.amask = 0xFF000000;
|
|
|
|
|
|
|
|
m.rsize = 8;
|
|
|
|
m.gsize = 8;
|
|
|
|
m.bsize = 8;
|
|
|
|
m.asize = 8;
|
2010-08-31 01:39:08 +00:00
|
|
|
|
|
|
|
m.pixelType = PixelType_UnsignedNorm;
|
2011-09-13 17:08:09 +00:00
|
|
|
m.pitchAlignment = 1;
|
2009-07-06 09:03:12 +00:00
|
|
|
|
2010-11-03 18:53:51 +00:00
|
|
|
m.enableColorDithering = false;
|
|
|
|
m.enableAlphaDithering = false;
|
|
|
|
m.binaryAlpha = false;
|
|
|
|
m.alphaThreshold = 127;
|
2011-02-28 08:27:24 +00:00
|
|
|
|
|
|
|
m.decoder = Decoder_D3D10;
|
2007-05-17 00:11:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Set desired compression format.
|
|
|
|
void CompressionOptions::setFormat(Format format)
|
|
|
|
{
|
2010-11-03 18:53:51 +00:00
|
|
|
m.format = format;
|
2007-05-17 00:11:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Set compression quality settings.
|
2008-01-18 23:50:22 +00:00
|
|
|
void CompressionOptions::setQuality(Quality quality)
|
2007-05-17 00:11:38 +00:00
|
|
|
{
|
2010-11-03 18:53:51 +00:00
|
|
|
m.quality = quality;
|
2007-05-17 00:11:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Set the weights of each color channel.
|
2010-11-10 03:28:44 +00:00
|
|
|
/// The choice for these values is subjective. In most cases uniform color weights
|
2007-05-17 00:11:38 +00:00
|
|
|
/// (1.0, 1.0, 1.0) work very well. A popular choice is to use the NTSC luma encoding
|
|
|
|
/// weights (0.2126, 0.7152, 0.0722), but I think that blue contributes to our
|
2007-12-13 06:29:03 +00:00
|
|
|
/// perception more than a 7%. A better choice in my opinion is (3, 4, 2).
|
2008-01-18 06:11:58 +00:00
|
|
|
void CompressionOptions::setColorWeights(float red, float green, float blue, float alpha/*=1.0f*/)
|
2007-05-17 00:11:38 +00:00
|
|
|
{
|
2011-01-08 04:54:06 +00:00
|
|
|
// float total = red + green + blue;
|
|
|
|
// float x = red / total;
|
|
|
|
// float y = green / total;
|
|
|
|
// m.colorWeight.set(x, y, 1.0f - x - y);
|
2010-11-03 18:53:51 +00:00
|
|
|
m.colorWeight.set(red, green, blue, alpha);
|
2007-05-17 00:11:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Set color mask to describe the RGB/RGBA format.
|
2010-08-31 01:39:08 +00:00
|
|
|
void CompressionOptions::setPixelFormat(uint bitCount, uint rmask, uint gmask, uint bmask, uint amask)
|
2007-05-17 00:11:38 +00:00
|
|
|
{
|
2010-11-03 18:53:51 +00:00
|
|
|
// Validate arguments.
|
2010-08-31 01:39:08 +00:00
|
|
|
nvCheck(bitCount <= 32);
|
2010-11-03 18:53:51 +00:00
|
|
|
nvCheck((rmask & gmask) == 0);
|
|
|
|
nvCheck((rmask & bmask) == 0);
|
|
|
|
nvCheck((rmask & amask) == 0);
|
|
|
|
nvCheck((gmask & bmask) == 0);
|
|
|
|
nvCheck((gmask & amask) == 0);
|
|
|
|
nvCheck((bmask & amask) == 0);
|
|
|
|
|
|
|
|
if (bitCount != 32)
|
|
|
|
{
|
|
|
|
uint maxMask = (1 << bitCount);
|
|
|
|
nvCheck(maxMask > rmask);
|
|
|
|
nvCheck(maxMask > gmask);
|
|
|
|
nvCheck(maxMask > bmask);
|
|
|
|
nvCheck(maxMask > amask);
|
|
|
|
}
|
|
|
|
|
|
|
|
m.bitcount = bitCount;
|
|
|
|
m.rmask = rmask;
|
|
|
|
m.gmask = gmask;
|
|
|
|
m.bmask = bmask;
|
|
|
|
m.amask = amask;
|
|
|
|
|
|
|
|
m.rsize = 0;
|
|
|
|
m.gsize = 0;
|
|
|
|
m.bsize = 0;
|
|
|
|
m.asize = 0;
|
2008-07-31 02:04:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CompressionOptions::setPixelFormat(uint8 rsize, uint8 gsize, uint8 bsize, uint8 asize)
|
|
|
|
{
|
2013-06-25 17:03:08 +00:00
|
|
|
nvCheck(rsize <= 32 && gsize <= 32 && bsize <= 32 && asize <= 32);
|
2010-11-03 18:53:51 +00:00
|
|
|
|
|
|
|
m.bitcount = 0;
|
|
|
|
m.rmask = 0;
|
|
|
|
m.gmask = 0;
|
|
|
|
m.bmask = 0;
|
|
|
|
m.amask = 0;
|
|
|
|
|
|
|
|
m.rsize = rsize;
|
|
|
|
m.gsize = gsize;
|
|
|
|
m.bsize = bsize;
|
|
|
|
m.asize = asize;
|
2007-05-17 00:11:38 +00:00
|
|
|
}
|
|
|
|
|
2008-07-31 02:04:44 +00:00
|
|
|
/// Set pixel type.
|
|
|
|
void CompressionOptions::setPixelType(PixelType pixelType)
|
|
|
|
{
|
2010-11-03 18:53:51 +00:00
|
|
|
m.pixelType = pixelType;
|
2008-07-31 02:04:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-08-31 01:39:08 +00:00
|
|
|
/// Set pitch alignment in bytes.
|
|
|
|
void CompressionOptions::setPitchAlignment(int pitchAlignment)
|
|
|
|
{
|
|
|
|
nvDebugCheck(pitchAlignment > 0 && isPowerOfTwo(pitchAlignment));
|
2010-11-03 18:53:51 +00:00
|
|
|
m.pitchAlignment = pitchAlignment;
|
2010-08-31 01:39:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-05-17 00:11:38 +00:00
|
|
|
/// Use external compressor.
|
|
|
|
void CompressionOptions::setExternalCompressor(const char * name)
|
|
|
|
{
|
2010-11-03 18:53:51 +00:00
|
|
|
m.externalCompressor = name;
|
2007-05-17 00:11:38 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 07:28:00 +00:00
|
|
|
/// Set quantization options.
|
|
|
|
/// @warning Do not enable dithering unless you know what you are doing. Quantization
|
|
|
|
/// introduces errors. It's better to let the compressor quantize the result to
|
|
|
|
/// minimize the error, instead of quantizing the data before handling it to
|
|
|
|
/// the compressor.
|
|
|
|
void CompressionOptions::setQuantization(bool colorDithering, bool alphaDithering, bool binaryAlpha, int alphaThreshold/*= 127*/)
|
|
|
|
{
|
2010-11-03 18:53:51 +00:00
|
|
|
nvCheck(alphaThreshold >= 0 && alphaThreshold < 256);
|
|
|
|
m.enableColorDithering = colorDithering;
|
|
|
|
m.enableAlphaDithering = alphaDithering;
|
|
|
|
m.binaryAlpha = binaryAlpha;
|
|
|
|
m.alphaThreshold = alphaThreshold;
|
2008-01-07 07:28:00 +00:00
|
|
|
}
|
|
|
|
|
2011-02-28 08:27:24 +00:00
|
|
|
/// Set target decoder to optimize for.
|
|
|
|
void CompressionOptions::setTargetDecoder(Decoder decoder)
|
|
|
|
{
|
|
|
|
m.decoder = decoder;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-07 07:28:00 +00:00
|
|
|
|
2011-01-08 04:54:06 +00:00
|
|
|
// Translate to and from D3D formats.
|
|
|
|
unsigned int CompressionOptions::d3d9Format() const
|
|
|
|
{
|
|
|
|
if (m.format == Format_RGB) {
|
|
|
|
if (m.pixelType == PixelType_UnsignedNorm) {
|
|
|
|
|
|
|
|
uint bitcount = m.bitcount;
|
|
|
|
uint rmask = m.rmask;
|
|
|
|
uint gmask = m.gmask;
|
|
|
|
uint bmask = m.bmask;
|
|
|
|
uint amask = m.amask;
|
|
|
|
|
|
|
|
if (bitcount == 0) {
|
|
|
|
bitcount = m.rsize + m.gsize + m.bsize + m.asize;
|
|
|
|
rmask = ((1 << m.rsize) - 1) << (m.asize + m.bsize + m.gsize);
|
|
|
|
gmask = ((1 << m.gsize) - 1) << (m.asize + m.bsize);
|
|
|
|
bmask = ((1 << m.bsize) - 1) << m.asize;
|
|
|
|
amask = ((1 << m.asize) - 1) << 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bitcount <= 32) {
|
|
|
|
return nv::findD3D9Format(bitcount, rmask, gmask, bmask, amask);
|
|
|
|
}
|
2011-04-06 02:41:15 +00:00
|
|
|
else {
|
|
|
|
//if (m.rsize == 16 && m.gsize == 16 && m.bsize == 0 && m.asize == 0) return D3DFMT_G16R16;
|
|
|
|
if (m.rsize == 16 && m.gsize == 16 && m.bsize == 16 && m.asize == 16) return D3DFMT_A16B16G16R16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (m.pixelType == PixelType_Float) {
|
|
|
|
if (m.rsize == 16 && m.gsize == 0 && m.bsize == 0 && m.asize == 0) return D3DFMT_R16F;
|
|
|
|
if (m.rsize == 32 && m.gsize == 0 && m.bsize == 0 && m.asize == 0) return D3DFMT_R32F;
|
|
|
|
if (m.rsize == 16 && m.gsize == 16 && m.bsize == 0 && m.asize == 0) return D3DFMT_G16R16F;
|
|
|
|
if (m.rsize == 32 && m.gsize == 32 && m.bsize == 0 && m.asize == 0) return D3DFMT_G32R32F;
|
|
|
|
if (m.rsize == 16 && m.gsize == 16 && m.bsize == 16 && m.asize == 16) return D3DFMT_A16B16G16R16F;
|
|
|
|
if (m.rsize == 32 && m.gsize == 32 && m.bsize == 32 && m.asize == 32) return D3DFMT_A32B32G32R32F;
|
2011-01-08 04:54:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
uint d3d9_formats[] = {
|
|
|
|
0, // Format_RGB,
|
|
|
|
FOURCC_DXT1, // Format_DXT1
|
|
|
|
FOURCC_DXT1, // Format_DXT1a
|
|
|
|
FOURCC_DXT3, // Format_DXT3
|
|
|
|
FOURCC_DXT5, // Format_DXT5
|
|
|
|
FOURCC_DXT5, // Format_DXT5n
|
|
|
|
FOURCC_ATI1, // Format_BC4
|
|
|
|
FOURCC_ATI2, // Format_BC5
|
|
|
|
FOURCC_DXT1, // Format_DXT1n
|
|
|
|
0, // Format_CTX1
|
2014-11-04 17:49:29 +00:00
|
|
|
MAKEFOURCC('B', 'C', '6', 'H'), // Format_BC6
|
|
|
|
MAKEFOURCC('B', 'C', '7', 'L'), // Format_BC7
|
2015-03-24 19:14:49 +00:00
|
|
|
//FOURCC_ATI2, // Format_BC5_Luma
|
2014-11-04 17:49:29 +00:00
|
|
|
FOURCC_DXT5, // Format_BC3_RGBM
|
2011-01-08 04:54:06 +00:00
|
|
|
};
|
|
|
|
|
2014-11-04 17:49:29 +00:00
|
|
|
NV_COMPILER_CHECK(NV_ARRAY_SIZE(d3d9_formats) == Format_Count);
|
|
|
|
|
2011-01-08 04:54:06 +00:00
|
|
|
return d3d9_formats[m.format];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
bool CompressionOptions::setDirect3D9Format(unsigned int format)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int CompressionOptions::dxgiFormat() const
|
|
|
|
{
|
|
|
|
}
|
2008-01-07 07:28:00 +00:00
|
|
|
|
2011-01-08 04:54:06 +00:00
|
|
|
bool CompressionOptions::setDXGIFormat(unsigned int format)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
*/
|