2010-11-06 02:34:34 +00:00
|
|
|
// Copyright (c) 2009-2011 Ignacio Castano <castano@gmail.com>
|
|
|
|
// Copyright (c) 2008-2009 NVIDIA Corporation -- Ignacio Castano <icastano@nvidia.com>
|
2008-01-30 08:21:55 +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.
|
|
|
|
|
2009-03-02 07:32:00 +00:00
|
|
|
#include "Context.h"
|
|
|
|
|
2010-11-03 18:31:16 +00:00
|
|
|
#include "nvtt.h"
|
2008-01-30 08:21:55 +00:00
|
|
|
|
|
|
|
#include "InputOptions.h"
|
|
|
|
#include "CompressionOptions.h"
|
|
|
|
#include "OutputOptions.h"
|
2011-09-28 16:46:01 +00:00
|
|
|
#include "Surface.h"
|
2008-01-30 08:21:55 +00:00
|
|
|
|
2010-06-03 07:07:37 +00:00
|
|
|
#include "CompressorDX9.h"
|
2010-05-31 08:13:23 +00:00
|
|
|
#include "CompressorDX10.h"
|
|
|
|
#include "CompressorDX11.h"
|
2010-03-16 22:37:25 +00:00
|
|
|
#include "CompressorRGB.h"
|
2008-01-30 08:21:55 +00:00
|
|
|
#include "cuda/CudaUtils.h"
|
2010-03-16 22:37:25 +00:00
|
|
|
#include "cuda/CudaCompressorDXT.h"
|
2008-01-30 08:21:55 +00:00
|
|
|
|
2010-11-03 18:31:16 +00:00
|
|
|
#include "nvimage/DirectDrawSurface.h"
|
|
|
|
#include "nvimage/ColorBlock.h"
|
|
|
|
#include "nvimage/BlockDXT.h"
|
|
|
|
#include "nvimage/Image.h"
|
|
|
|
#include "nvimage/FloatImage.h"
|
|
|
|
#include "nvimage/Filter.h"
|
|
|
|
#include "nvimage/Quantize.h"
|
|
|
|
#include "nvimage/NormalMap.h"
|
|
|
|
#include "nvimage/PixelFormat.h"
|
|
|
|
#include "nvimage/ColorSpace.h"
|
|
|
|
|
|
|
|
#include "nvcore/Memory.h"
|
|
|
|
#include "nvcore/Ptr.h"
|
|
|
|
|
2008-01-30 08:21:55 +00:00
|
|
|
using namespace nv;
|
|
|
|
using namespace nvtt;
|
|
|
|
|
|
|
|
Compressor::Compressor() : m(*new Compressor::Private())
|
|
|
|
{
|
2010-06-24 07:32:17 +00:00
|
|
|
// CUDA initialization.
|
|
|
|
m.cudaSupported = cuda::isHardwarePresent();
|
2010-11-03 18:31:16 +00:00
|
|
|
m.cudaEnabled = false;
|
|
|
|
m.cuda = NULL;
|
2010-06-24 07:32:17 +00:00
|
|
|
|
2010-11-03 18:31:16 +00:00
|
|
|
enableCudaAcceleration(m.cudaSupported);
|
2010-12-10 10:29:04 +00:00
|
|
|
|
|
|
|
m.dispatcher = &m.defaultDispatcher;
|
2008-01-30 08:21:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Compressor::~Compressor()
|
|
|
|
{
|
2010-06-24 07:32:17 +00:00
|
|
|
delete &m;
|
2008-01-30 08:21:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-01 19:50:19 +00:00
|
|
|
void Compressor::enableCudaAcceleration(bool enable)
|
2008-01-30 08:21:55 +00:00
|
|
|
{
|
2010-06-24 07:32:17 +00:00
|
|
|
if (m.cudaSupported)
|
|
|
|
{
|
|
|
|
m.cudaEnabled = enable;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m.cudaEnabled && m.cuda == NULL)
|
|
|
|
{
|
2010-11-22 07:34:05 +00:00
|
|
|
m.cuda = new CudaContext();
|
|
|
|
|
|
|
|
if (!m.cuda->isValid())
|
2010-06-24 07:32:17 +00:00
|
|
|
{
|
|
|
|
m.cudaEnabled = false;
|
|
|
|
m.cuda = NULL;
|
|
|
|
}
|
|
|
|
}
|
2008-01-30 08:21:55 +00:00
|
|
|
}
|
|
|
|
|
2008-02-01 19:50:19 +00:00
|
|
|
bool Compressor::isCudaAccelerationEnabled() const
|
2008-01-30 08:21:55 +00:00
|
|
|
{
|
2010-06-24 07:32:17 +00:00
|
|
|
return m.cudaEnabled;
|
2008-01-30 08:21:55 +00:00
|
|
|
}
|
|
|
|
|
2010-12-10 10:29:04 +00:00
|
|
|
void Compressor::setTaskDispatcher(TaskDispatcher * disp)
|
|
|
|
{
|
|
|
|
if (disp == NULL) {
|
|
|
|
m.dispatcher = &m.defaultDispatcher;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m.dispatcher = disp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-30 08:21:55 +00:00
|
|
|
|
2010-11-03 18:31:16 +00:00
|
|
|
// Input Options API.
|
2008-01-30 08:21:55 +00:00
|
|
|
bool Compressor::process(const InputOptions & inputOptions, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const
|
|
|
|
{
|
2010-06-24 07:32:17 +00:00
|
|
|
return m.compress(inputOptions.m, compressionOptions.m, outputOptions.m);
|
2008-01-30 08:21:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int Compressor::estimateSize(const InputOptions & inputOptions, const CompressionOptions & compressionOptions) const
|
|
|
|
{
|
2010-11-05 00:36:50 +00:00
|
|
|
int w = inputOptions.m.width;
|
|
|
|
int h = inputOptions.m.height;
|
|
|
|
int d = inputOptions.m.depth;
|
2011-12-12 18:05:04 +00:00
|
|
|
|
|
|
|
getTargetExtent(&w, &h, &d, inputOptions.m.maxExtent, inputOptions.m.roundMode, inputOptions.m.textureType);
|
2010-11-03 18:31:16 +00:00
|
|
|
|
2011-09-27 05:17:01 +00:00
|
|
|
int mipmapCount = 1;
|
|
|
|
if (inputOptions.m.generateMipmaps) {
|
|
|
|
mipmapCount = countMipmaps(w, h, d);
|
|
|
|
if (inputOptions.m.maxLevel > 0) mipmapCount = min(mipmapCount, inputOptions.m.maxLevel);
|
|
|
|
}
|
|
|
|
|
2010-11-03 18:31:16 +00:00
|
|
|
return inputOptions.m.faceCount * estimateSize(w, h, d, mipmapCount, compressionOptions);
|
2008-01-30 08:21:55 +00:00
|
|
|
}
|
|
|
|
|
2009-10-21 07:48:27 +00:00
|
|
|
|
2011-09-28 16:40:59 +00:00
|
|
|
// Surface API.
|
|
|
|
bool Compressor::outputHeader(const Surface & tex, int mipmapCount, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const
|
2009-03-16 08:37:07 +00:00
|
|
|
{
|
2011-09-27 05:17:01 +00:00
|
|
|
return m.outputHeader(tex.type(), tex.width(), tex.height(), tex.depth(), mipmapCount, tex.isNormalMap(), compressionOptions.m, outputOptions.m);
|
2009-03-16 08:37:07 +00:00
|
|
|
}
|
|
|
|
|
2011-09-28 16:40:59 +00:00
|
|
|
bool Compressor::compress(const Surface & tex, int face, int mipmap, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const
|
2009-03-16 08:37:07 +00:00
|
|
|
{
|
2010-11-06 02:34:34 +00:00
|
|
|
return m.compress(tex, face, mipmap, compressionOptions.m, outputOptions.m);
|
2009-10-12 07:56:02 +00:00
|
|
|
}
|
|
|
|
|
2011-09-28 16:40:59 +00:00
|
|
|
int Compressor::estimateSize(const Surface & tex, int mipmapCount, const CompressionOptions & compressionOptions) const
|
2009-10-12 07:56:02 +00:00
|
|
|
{
|
2010-11-03 18:31:16 +00:00
|
|
|
const int w = tex.width();
|
|
|
|
const int h = tex.height();
|
|
|
|
const int d = tex.depth();
|
|
|
|
|
2010-11-05 00:36:50 +00:00
|
|
|
return estimateSize(w, h, d, mipmapCount, compressionOptions);
|
2009-10-12 07:56:02 +00:00
|
|
|
}
|
|
|
|
|
2011-09-28 16:40:59 +00:00
|
|
|
bool Compressor::outputHeader(const CubeSurface & cube, int mipmapCount, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const
|
2011-09-28 01:45:08 +00:00
|
|
|
{
|
2011-09-29 00:58:47 +00:00
|
|
|
return m.outputHeader(TextureType_Cube, cube.edgeLength(), cube.edgeLength(), 1, mipmapCount, false, compressionOptions.m, outputOptions.m);
|
2011-09-28 01:45:08 +00:00
|
|
|
}
|
|
|
|
|
2011-09-28 16:40:59 +00:00
|
|
|
bool Compressor::compress(const CubeSurface & cube, int mipmap, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const
|
2011-09-28 01:45:08 +00:00
|
|
|
{
|
|
|
|
for (int i = 0; i < 6; i++) {
|
|
|
|
if(!m.compress(cube.face(i), i, mipmap, compressionOptions.m, outputOptions.m)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-09-28 16:40:59 +00:00
|
|
|
int Compressor::estimateSize(const CubeSurface & cube, int mipmapCount, const CompressionOptions & compressionOptions) const
|
2011-09-28 01:45:08 +00:00
|
|
|
{
|
2011-09-29 00:58:47 +00:00
|
|
|
return 6 * estimateSize(cube.edgeLength(), cube.edgeLength(), 1, mipmapCount, compressionOptions);
|
2011-09-28 01:45:08 +00:00
|
|
|
}
|
|
|
|
|
2009-10-21 07:48:27 +00:00
|
|
|
|
2010-11-03 18:31:16 +00:00
|
|
|
// Raw API.
|
2011-04-06 02:41:15 +00:00
|
|
|
bool Compressor::outputHeader(TextureType type, int w, int h, int d, int mipmapCount, bool isNormalMap, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const
|
|
|
|
{
|
|
|
|
return m.outputHeader(type, w, h, d, mipmapCount, isNormalMap, compressionOptions.m, outputOptions.m);
|
|
|
|
}
|
|
|
|
|
2010-11-06 02:34:34 +00:00
|
|
|
bool Compressor::compress(int w, int h, int d, int face, int mipmap, const float * rgba, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const
|
2009-10-12 07:56:02 +00:00
|
|
|
{
|
2010-11-06 02:34:34 +00:00
|
|
|
return m.compress(AlphaMode_None, w, h, d, face, mipmap, rgba, compressionOptions.m, outputOptions.m);
|
2009-10-12 07:56:02 +00:00
|
|
|
}
|
|
|
|
|
2010-11-03 18:31:16 +00:00
|
|
|
int Compressor::estimateSize(int w, int h, int d, int mipmapCount, const CompressionOptions & compressionOptions) const
|
2009-10-12 07:56:02 +00:00
|
|
|
{
|
2010-11-03 18:31:16 +00:00
|
|
|
const Format format = compressionOptions.m.format;
|
2010-05-28 23:16:06 +00:00
|
|
|
|
2010-11-03 18:31:16 +00:00
|
|
|
const uint bitCount = compressionOptions.m.getBitCount();
|
|
|
|
const uint pitchAlignment = compressionOptions.m.pitchAlignment;
|
2009-10-12 07:56:02 +00:00
|
|
|
|
2010-11-03 18:31:16 +00:00
|
|
|
int size = 0;
|
|
|
|
for (int m = 0; m < mipmapCount; m++)
|
|
|
|
{
|
|
|
|
size += computeImageSize(w, h, d, bitCount, pitchAlignment, format);
|
|
|
|
|
|
|
|
// Compute extents of next mipmap:
|
|
|
|
w = max(1, w / 2);
|
|
|
|
h = max(1, h / 2);
|
|
|
|
d = max(1, d / 2);
|
|
|
|
}
|
2009-03-16 08:37:07 +00:00
|
|
|
|
2010-11-03 18:31:16 +00:00
|
|
|
return size;
|
2009-03-16 08:37:07 +00:00
|
|
|
}
|
|
|
|
|
2008-01-30 08:21:55 +00:00
|
|
|
|
2009-10-21 07:48:27 +00:00
|
|
|
|
|
|
|
|
2010-11-03 18:31:16 +00:00
|
|
|
|
2008-01-30 08:21:55 +00:00
|
|
|
bool Compressor::Private::compress(const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const
|
|
|
|
{
|
2010-06-24 07:32:17 +00:00
|
|
|
// Make sure enums match.
|
|
|
|
nvStaticCheck(FloatImage::WrapMode_Clamp == (FloatImage::WrapMode)WrapMode_Clamp);
|
|
|
|
nvStaticCheck(FloatImage::WrapMode_Mirror == (FloatImage::WrapMode)WrapMode_Mirror);
|
|
|
|
nvStaticCheck(FloatImage::WrapMode_Repeat == (FloatImage::WrapMode)WrapMode_Repeat);
|
|
|
|
|
|
|
|
// Get output handler.
|
2011-12-12 18:05:04 +00:00
|
|
|
if (!outputOptions.hasValidOutputHandler()) {
|
2010-06-24 07:32:17 +00:00
|
|
|
outputOptions.error(Error_FileOpen);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-09-28 16:40:59 +00:00
|
|
|
nvtt::Surface img;
|
2010-11-03 18:31:16 +00:00
|
|
|
img.setWrapMode(inputOptions.wrapMode);
|
|
|
|
img.setAlphaMode(inputOptions.alphaMode);
|
|
|
|
img.setNormalMap(inputOptions.isNormalMap);
|
2010-06-24 07:32:17 +00:00
|
|
|
|
2010-11-03 18:31:16 +00:00
|
|
|
const int faceCount = inputOptions.faceCount;
|
2011-12-12 18:05:04 +00:00
|
|
|
int width = inputOptions.width;
|
|
|
|
int height = inputOptions.height;
|
|
|
|
int depth = inputOptions.depth;
|
2010-11-03 18:31:16 +00:00
|
|
|
|
2011-12-12 18:05:04 +00:00
|
|
|
nv::getTargetExtent(&width, &height, &depth, inputOptions.maxExtent, inputOptions.roundMode, inputOptions.textureType);
|
2008-01-30 08:21:55 +00:00
|
|
|
|
2010-11-05 00:36:50 +00:00
|
|
|
// If the extents have not changed, then we can use source images for all mipmaps.
|
2011-12-12 18:05:04 +00:00
|
|
|
bool canUseSourceImages = (inputOptions.width == width && inputOptions.height == height && inputOptions.depth == depth);
|
2008-01-30 08:21:55 +00:00
|
|
|
|
2010-11-03 18:31:16 +00:00
|
|
|
int mipmapCount = 1;
|
|
|
|
if (inputOptions.generateMipmaps) {
|
2011-12-12 18:05:04 +00:00
|
|
|
mipmapCount = countMipmaps(width, height, depth);
|
2010-11-03 18:31:16 +00:00
|
|
|
if (inputOptions.maxLevel > 0) mipmapCount = min(mipmapCount, inputOptions.maxLevel);
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
|
2011-12-12 18:05:04 +00:00
|
|
|
if (!outputHeader(inputOptions.textureType, width, height, depth, mipmapCount, img.isNormalMap(), compressionOptions, outputOptions)) {
|
2010-11-03 18:31:16 +00:00
|
|
|
return false;
|
|
|
|
}
|
2010-08-31 01:39:08 +00:00
|
|
|
|
|
|
|
|
2010-11-05 00:36:50 +00:00
|
|
|
// Output images.
|
|
|
|
for (int f = 0; f < faceCount; f++)
|
|
|
|
{
|
2011-12-12 18:05:04 +00:00
|
|
|
int w = width;
|
|
|
|
int h = height;
|
|
|
|
int d = depth;
|
|
|
|
bool canUseSourceImagesForThisFace = canUseSourceImages;
|
|
|
|
|
2011-09-27 05:17:01 +00:00
|
|
|
img.setImage(inputOptions.inputFormat, inputOptions.width, inputOptions.height, inputOptions.depth, inputOptions.images[f]);
|
2010-11-05 00:36:50 +00:00
|
|
|
|
|
|
|
// To normal map.
|
|
|
|
if (inputOptions.convertToNormalMap) {
|
|
|
|
img.toGreyScale(inputOptions.heightFactors.x, inputOptions.heightFactors.y, inputOptions.heightFactors.z, inputOptions.heightFactors.w);
|
|
|
|
img.toNormalMap(inputOptions.bumpFrequencyScale.x, inputOptions.bumpFrequencyScale.y, inputOptions.bumpFrequencyScale.z, inputOptions.bumpFrequencyScale.w);
|
|
|
|
}
|
2010-08-31 01:39:08 +00:00
|
|
|
|
2010-11-05 00:36:50 +00:00
|
|
|
// To linear space.
|
|
|
|
if (!img.isNormalMap()) {
|
|
|
|
img.toLinear(inputOptions.inputGamma);
|
|
|
|
}
|
2013-07-20 00:08:06 +00:00
|
|
|
else {
|
|
|
|
img.expandNormals();
|
|
|
|
}
|
2010-06-24 07:32:17 +00:00
|
|
|
|
2010-11-05 00:36:50 +00:00
|
|
|
// Resize input.
|
2011-09-27 05:17:01 +00:00
|
|
|
img.resize(w, h, d, ResizeFilter_Box);
|
2010-11-05 00:36:50 +00:00
|
|
|
|
2011-09-28 16:40:59 +00:00
|
|
|
nvtt::Surface tmp = img;
|
2010-11-05 00:36:50 +00:00
|
|
|
if (!img.isNormalMap()) {
|
|
|
|
tmp.toGamma(inputOptions.outputGamma);
|
|
|
|
}
|
2013-07-20 00:08:06 +00:00
|
|
|
else {
|
|
|
|
tmp.packNormals();
|
|
|
|
}
|
2010-06-24 07:32:17 +00:00
|
|
|
|
2010-11-05 00:36:50 +00:00
|
|
|
quantize(tmp, compressionOptions);
|
2010-11-06 02:34:34 +00:00
|
|
|
compress(tmp, f, 0, compressionOptions, outputOptions);
|
2010-06-24 07:32:17 +00:00
|
|
|
|
2010-11-05 00:36:50 +00:00
|
|
|
for (int m = 1; m < mipmapCount; m++) {
|
|
|
|
w = max(1, w/2);
|
|
|
|
h = max(1, h/2);
|
|
|
|
d = max(1, d/2);
|
|
|
|
|
|
|
|
int idx = m * faceCount + f;
|
|
|
|
|
|
|
|
bool useSourceImages = false;
|
2011-12-12 18:05:04 +00:00
|
|
|
if (canUseSourceImagesForThisFace) {
|
2010-11-03 18:31:16 +00:00
|
|
|
if (inputOptions.images[idx] == NULL) { // One face is missing in this mipmap level.
|
2011-12-12 18:05:04 +00:00
|
|
|
canUseSourceImagesForThisFace = false; // If one level is missing, ignore the following source images.
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
useSourceImages = true;
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-05 00:36:50 +00:00
|
|
|
if (useSourceImages) {
|
2011-09-27 05:17:01 +00:00
|
|
|
img.setImage(inputOptions.inputFormat, w, h, d, inputOptions.images[idx]);
|
|
|
|
|
|
|
|
// For already generated mipmaps, we need to convert to linear.
|
|
|
|
if (!img.isNormalMap()) {
|
|
|
|
img.toLinear(inputOptions.inputGamma);
|
|
|
|
}
|
2013-07-20 00:08:06 +00:00
|
|
|
else {
|
|
|
|
img.expandNormals();
|
|
|
|
}
|
2010-11-03 18:31:16 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-11-05 00:36:50 +00:00
|
|
|
if (inputOptions.mipmapFilter == MipmapFilter_Kaiser) {
|
|
|
|
float params[2] = { inputOptions.kaiserStretch, inputOptions.kaiserAlpha };
|
|
|
|
img.buildNextMipmap(MipmapFilter_Kaiser, inputOptions.kaiserWidth, params);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
img.buildNextMipmap(inputOptions.mipmapFilter);
|
|
|
|
}
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
2010-11-05 00:36:50 +00:00
|
|
|
nvDebugCheck(img.width() == w);
|
|
|
|
nvDebugCheck(img.height() == h);
|
2011-09-27 05:17:01 +00:00
|
|
|
nvDebugCheck(img.depth() == d);
|
2010-06-24 07:32:17 +00:00
|
|
|
|
2010-11-05 00:36:50 +00:00
|
|
|
if (img.isNormalMap()) {
|
|
|
|
if (inputOptions.normalizeMipmaps) {
|
|
|
|
img.normalizeNormalMap();
|
|
|
|
}
|
|
|
|
tmp = img;
|
2013-07-20 00:08:06 +00:00
|
|
|
tmp.packNormals();
|
2010-11-05 00:36:50 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
tmp = img;
|
|
|
|
tmp.toGamma(inputOptions.outputGamma);
|
2010-11-03 18:31:16 +00:00
|
|
|
}
|
2010-06-24 07:32:17 +00:00
|
|
|
|
2010-11-05 00:36:50 +00:00
|
|
|
quantize(tmp, compressionOptions);
|
2010-11-06 02:34:34 +00:00
|
|
|
compress(tmp, f, m, compressionOptions, outputOptions);
|
2010-11-05 00:36:50 +00:00
|
|
|
}
|
|
|
|
}
|
2010-06-24 07:32:17 +00:00
|
|
|
|
2010-11-03 18:31:16 +00:00
|
|
|
return true;
|
|
|
|
}
|
2010-06-24 07:32:17 +00:00
|
|
|
|
2011-09-28 16:40:59 +00:00
|
|
|
bool Compressor::Private::compress(const Surface & tex, int face, int mipmap, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const
|
2010-11-03 18:31:16 +00:00
|
|
|
{
|
2010-11-06 02:34:34 +00:00
|
|
|
if (!compress(tex.alphaMode(), tex.width(), tex.height(), tex.depth(), face, mipmap, tex.data(), compressionOptions, outputOptions)) {
|
2010-11-05 00:36:50 +00:00
|
|
|
return false;
|
2010-11-03 18:31:16 +00:00
|
|
|
}
|
2010-11-05 00:36:50 +00:00
|
|
|
|
2010-06-24 07:32:17 +00:00
|
|
|
return true;
|
2008-01-30 08:21:55 +00:00
|
|
|
}
|
|
|
|
|
2010-11-06 02:34:34 +00:00
|
|
|
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
|
2010-11-03 18:53:51 +00:00
|
|
|
{
|
2011-09-27 05:17:01 +00:00
|
|
|
int size = computeImageSize(w, h, d, compressionOptions.getBitCount(), compressionOptions.pitchAlignment, compressionOptions.format);
|
2010-11-06 02:34:34 +00:00
|
|
|
outputOptions.beginImage(size, w, h, d, face, mipmap);
|
|
|
|
|
2010-11-03 18:53:51 +00:00
|
|
|
// Decide what compressor to use.
|
|
|
|
AutoPtr<CompressorInterface> compressor;
|
|
|
|
#if defined HAVE_CUDA
|
|
|
|
if (cudaEnabled && w * h >= 512)
|
|
|
|
{
|
|
|
|
compressor = chooseGpuCompressor(compressionOptions);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (compressor == NULL)
|
|
|
|
{
|
|
|
|
compressor = chooseCpuCompressor(compressionOptions);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (compressor == NULL)
|
|
|
|
{
|
|
|
|
outputOptions.error(Error_UnsupportedFeature);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-09-27 05:17:01 +00:00
|
|
|
compressor->compress(alphaMode, w, h, d, rgba, dispatcher, compressionOptions, outputOptions);
|
2010-11-03 18:53:51 +00:00
|
|
|
}
|
|
|
|
|
2011-09-27 17:48:46 +00:00
|
|
|
outputOptions.endImage();
|
|
|
|
|
2010-11-03 18:53:51 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-28 16:40:59 +00:00
|
|
|
void Compressor::Private::quantize(Surface & img, const CompressionOptions::Private & compressionOptions) const
|
2010-11-03 18:53:51 +00:00
|
|
|
{
|
|
|
|
if (compressionOptions.enableColorDithering) {
|
|
|
|
if (compressionOptions.format >= Format_BC1 && compressionOptions.format <= Format_BC3) {
|
2011-01-25 09:17:53 +00:00
|
|
|
img.quantize(0, 5, true, true);
|
|
|
|
img.quantize(1, 6, true, true);
|
|
|
|
img.quantize(2, 5, true, true);
|
2010-11-03 18:53:51 +00:00
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_RGB) {
|
2011-01-25 09:17:53 +00:00
|
|
|
img.quantize(0, compressionOptions.rsize, true, true);
|
|
|
|
img.quantize(1, compressionOptions.gsize, true, true);
|
|
|
|
img.quantize(2, compressionOptions.bsize, true, true);
|
2010-11-03 18:53:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (compressionOptions.enableAlphaDithering) {
|
|
|
|
if (compressionOptions.format == Format_RGB) {
|
2011-01-25 09:17:53 +00:00
|
|
|
img.quantize(3, compressionOptions.asize, true, true);
|
2010-11-03 18:53:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (compressionOptions.binaryAlpha) {
|
2010-11-06 02:34:34 +00:00
|
|
|
img.binarize(3, float(compressionOptions.alphaThreshold)/255.0f, compressionOptions.enableAlphaDithering);
|
2010-11-03 18:53:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-03 18:31:16 +00:00
|
|
|
|
2010-11-05 00:36:50 +00:00
|
|
|
bool Compressor::Private::outputHeader(nvtt::TextureType textureType, int w, int h, int d, int mipmapCount, bool isNormalMap, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const
|
2009-10-12 07:56:02 +00:00
|
|
|
{
|
2010-11-05 00:36:50 +00:00
|
|
|
if (w <= 0 || h <= 0 || d <= 0 || mipmapCount <= 0)
|
2010-06-24 07:32:17 +00:00
|
|
|
{
|
|
|
|
outputOptions.error(Error_InvalidInput);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!outputOptions.outputHeader)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Output DDS header.
|
|
|
|
if (outputOptions.container == Container_DDS || outputOptions.container == Container_DDS10)
|
|
|
|
{
|
|
|
|
DDSHeader header;
|
|
|
|
|
2010-08-31 01:39:08 +00:00
|
|
|
header.setUserVersion(outputOptions.version);
|
|
|
|
|
2010-11-05 00:36:50 +00:00
|
|
|
if (textureType == TextureType_2D) {
|
2010-08-31 01:39:08 +00:00
|
|
|
header.setTexture2D();
|
|
|
|
}
|
2010-11-05 00:36:50 +00:00
|
|
|
else if (textureType == TextureType_Cube) {
|
2010-08-31 01:39:08 +00:00
|
|
|
header.setTextureCube();
|
|
|
|
}
|
2011-09-27 05:17:01 +00:00
|
|
|
else if (textureType == TextureType_3D) {
|
2010-08-31 01:39:08 +00:00
|
|
|
header.setTexture3D();
|
2010-11-05 00:36:50 +00:00
|
|
|
header.setDepth(d);
|
2011-09-27 05:17:01 +00:00
|
|
|
}
|
2010-08-31 01:39:08 +00:00
|
|
|
|
2010-11-05 00:36:50 +00:00
|
|
|
header.setWidth(w);
|
|
|
|
header.setHeight(h);
|
2010-06-24 07:32:17 +00:00
|
|
|
header.setMipmapCount(mipmapCount);
|
|
|
|
|
|
|
|
bool supported = true;
|
|
|
|
|
|
|
|
if (outputOptions.container == Container_DDS10)
|
|
|
|
{
|
|
|
|
if (compressionOptions.format == Format_RGBA)
|
|
|
|
{
|
2011-09-27 05:17:01 +00:00
|
|
|
const uint bitcount = compressionOptions.getBitCount();
|
2010-06-24 07:32:17 +00:00
|
|
|
|
|
|
|
if (bitcount == 16)
|
|
|
|
{
|
|
|
|
if (compressionOptions.rsize == 16)
|
|
|
|
{
|
|
|
|
header.setDX10Format(56); // R16_UNORM
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// B5G6R5_UNORM
|
|
|
|
// B5G5R5A1_UNORM
|
|
|
|
supported = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (bitcount == 32)
|
|
|
|
{
|
|
|
|
// B8G8R8A8_UNORM
|
|
|
|
// B8G8R8X8_UNORM
|
|
|
|
// R8G8B8A8_UNORM
|
|
|
|
// R10G10B10A2_UNORM
|
|
|
|
supported = false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
supported = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (compressionOptions.format == Format_DXT1 || compressionOptions.format == Format_DXT1a || compressionOptions.format == Format_DXT1n) {
|
2013-10-25 17:30:55 +00:00
|
|
|
header.setDX10Format(DXGI_FORMAT_BC1_UNORM);
|
2010-06-24 07:32:17 +00:00
|
|
|
if (compressionOptions.format == Format_DXT1a) header.setHasAlphaFlag(true);
|
2010-11-05 00:36:50 +00:00
|
|
|
if (isNormalMap) header.setNormalFlag(true);
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_DXT3) {
|
2013-10-25 17:30:55 +00:00
|
|
|
header.setDX10Format(DXGI_FORMAT_BC2_UNORM);
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_DXT5) {
|
2013-10-25 17:30:55 +00:00
|
|
|
header.setDX10Format(DXGI_FORMAT_BC3_UNORM);
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_DXT5n) {
|
2013-10-25 17:30:55 +00:00
|
|
|
header.setDX10Format(DXGI_FORMAT_BC3_UNORM);
|
2010-11-05 00:36:50 +00:00
|
|
|
if (isNormalMap) header.setNormalFlag(true);
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_BC4) {
|
2013-10-25 17:30:55 +00:00
|
|
|
header.setDX10Format(DXGI_FORMAT_BC4_UNORM);
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_BC5) {
|
2013-10-25 17:30:55 +00:00
|
|
|
header.setDX10Format(DXGI_FORMAT_BC5_UNORM);
|
2010-11-05 00:36:50 +00:00
|
|
|
if (isNormalMap) header.setNormalFlag(true);
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_BC6) {
|
2013-10-25 17:30:55 +00:00
|
|
|
header.setDX10Format(DXGI_FORMAT_BC6H_UF16);
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_BC7) {
|
2013-10-25 17:30:55 +00:00
|
|
|
header.setDX10Format(DXGI_FORMAT_BC7_UNORM);
|
2010-11-05 00:36:50 +00:00
|
|
|
if (isNormalMap) header.setNormalFlag(true);
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
supported = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (compressionOptions.format == Format_RGBA)
|
|
|
|
{
|
|
|
|
// Get output bit count.
|
2011-08-26 12:11:38 +00:00
|
|
|
header.setPitch(computeBytePitch(w, compressionOptions.getBitCount(), compressionOptions.pitchAlignment));
|
2010-06-24 07:32:17 +00:00
|
|
|
|
|
|
|
if (compressionOptions.pixelType == PixelType_Float)
|
|
|
|
{
|
|
|
|
if (compressionOptions.rsize == 16 && compressionOptions.gsize == 0 && compressionOptions.bsize == 0 && compressionOptions.asize == 0)
|
|
|
|
{
|
|
|
|
header.setFormatCode(111); // D3DFMT_R16F
|
|
|
|
}
|
|
|
|
else if (compressionOptions.rsize == 16 && compressionOptions.gsize == 16 && compressionOptions.bsize == 0 && compressionOptions.asize == 0)
|
|
|
|
{
|
|
|
|
header.setFormatCode(112); // D3DFMT_G16R16F
|
|
|
|
}
|
|
|
|
else if (compressionOptions.rsize == 16 && compressionOptions.gsize == 16 && compressionOptions.bsize == 16 && compressionOptions.asize == 16)
|
|
|
|
{
|
|
|
|
header.setFormatCode(113); // D3DFMT_A16B16G16R16F
|
|
|
|
}
|
|
|
|
else if (compressionOptions.rsize == 32 && compressionOptions.gsize == 0 && compressionOptions.bsize == 0 && compressionOptions.asize == 0)
|
|
|
|
{
|
|
|
|
header.setFormatCode(114); // D3DFMT_R32F
|
|
|
|
}
|
|
|
|
else if (compressionOptions.rsize == 32 && compressionOptions.gsize == 32 && compressionOptions.bsize == 0 && compressionOptions.asize == 0)
|
|
|
|
{
|
|
|
|
header.setFormatCode(115); // D3DFMT_G32R32F
|
|
|
|
}
|
|
|
|
else if (compressionOptions.rsize == 32 && compressionOptions.gsize == 32 && compressionOptions.bsize == 32 && compressionOptions.asize == 32)
|
|
|
|
{
|
|
|
|
header.setFormatCode(116); // D3DFMT_A32B32G32R32F
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
supported = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else // Fixed point
|
|
|
|
{
|
|
|
|
const uint bitcount = compressionOptions.getBitCount();
|
|
|
|
|
|
|
|
if (compressionOptions.bitcount != 0)
|
|
|
|
{
|
|
|
|
// Masks already computed.
|
|
|
|
header.setPixelFormat(compressionOptions.bitcount, compressionOptions.rmask, compressionOptions.gmask, compressionOptions.bmask, compressionOptions.amask);
|
|
|
|
}
|
|
|
|
else if (bitcount <= 32)
|
|
|
|
{
|
|
|
|
// Compute pixel format masks.
|
|
|
|
const uint ashift = 0;
|
|
|
|
const uint bshift = ashift + compressionOptions.asize;
|
|
|
|
const uint gshift = bshift + compressionOptions.bsize;
|
|
|
|
const uint rshift = gshift + compressionOptions.gsize;
|
|
|
|
|
|
|
|
const uint rmask = ((1 << compressionOptions.rsize) - 1) << rshift;
|
|
|
|
const uint gmask = ((1 << compressionOptions.gsize) - 1) << gshift;
|
|
|
|
const uint bmask = ((1 << compressionOptions.bsize) - 1) << bshift;
|
|
|
|
const uint amask = ((1 << compressionOptions.asize) - 1) << ashift;
|
|
|
|
|
|
|
|
header.setPixelFormat(bitcount, rmask, gmask, bmask, amask);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
supported = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-11-05 00:36:50 +00:00
|
|
|
header.setLinearSize(computeImageSize(w, h, d, compressionOptions.bitcount, compressionOptions.pitchAlignment, compressionOptions.format));
|
2010-06-24 07:32:17 +00:00
|
|
|
|
|
|
|
if (compressionOptions.format == Format_DXT1 || compressionOptions.format == Format_DXT1a || compressionOptions.format == Format_DXT1n) {
|
|
|
|
header.setFourCC('D', 'X', 'T', '1');
|
2010-11-05 00:36:50 +00:00
|
|
|
if (isNormalMap) header.setNormalFlag(true);
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_DXT3) {
|
|
|
|
header.setFourCC('D', 'X', 'T', '3');
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_DXT5) {
|
|
|
|
header.setFourCC('D', 'X', 'T', '5');
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_DXT5n) {
|
|
|
|
header.setFourCC('D', 'X', 'T', '5');
|
2010-11-05 00:36:50 +00:00
|
|
|
if (isNormalMap) {
|
2010-06-24 07:32:17 +00:00
|
|
|
header.setNormalFlag(true);
|
|
|
|
header.setSwizzleCode('A', '2', 'D', '5');
|
|
|
|
//header.setSwizzleCode('x', 'G', 'x', 'R');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_BC4) {
|
|
|
|
header.setFourCC('A', 'T', 'I', '1');
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_BC5) {
|
|
|
|
header.setFourCC('A', 'T', 'I', '2');
|
2010-11-05 00:36:50 +00:00
|
|
|
if (isNormalMap) {
|
2010-06-24 07:32:17 +00:00
|
|
|
header.setNormalFlag(true);
|
|
|
|
header.setSwizzleCode('A', '2', 'X', 'Y');
|
|
|
|
}
|
|
|
|
}
|
2011-01-08 04:54:06 +00:00
|
|
|
else if (compressionOptions.format == Format_BC6) { // @@ This is not supported by D3DX. Always use DX10 header with BC6-7 formats.
|
2010-06-24 07:32:17 +00:00
|
|
|
header.setFourCC('Z', 'O', 'H', ' ');
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_BC7) {
|
|
|
|
header.setFourCC('Z', 'O', 'L', 'A');
|
2010-11-05 00:36:50 +00:00
|
|
|
if (isNormalMap) header.setNormalFlag(true);
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_CTX1) {
|
|
|
|
header.setFourCC('C', 'T', 'X', '1');
|
2010-11-05 00:36:50 +00:00
|
|
|
if (isNormalMap) header.setNormalFlag(true);
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
supported = false;
|
|
|
|
}
|
|
|
|
}
|
2011-01-08 04:54:06 +00:00
|
|
|
|
|
|
|
if (outputOptions.srgb) header.setSrgbFlag(true);
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!supported)
|
|
|
|
{
|
|
|
|
// This container does not support the requested format.
|
|
|
|
outputOptions.error(Error_UnsupportedOutputFormat);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint headerSize = 128;
|
|
|
|
if (header.hasDX10Header())
|
|
|
|
{
|
|
|
|
nvStaticCheck(sizeof(DDSHeader) == 128 + 20);
|
|
|
|
headerSize = 128 + 20;
|
|
|
|
}
|
|
|
|
|
2011-01-08 04:54:06 +00:00
|
|
|
// Swap bytes if necessary.
|
|
|
|
header.swapBytes();
|
|
|
|
|
2010-08-31 01:39:08 +00:00
|
|
|
bool writeSucceed = outputOptions.writeData(&header, headerSize);
|
2010-06-24 07:32:17 +00:00
|
|
|
if (!writeSucceed)
|
|
|
|
{
|
|
|
|
outputOptions.error(Error_FileWrite);
|
|
|
|
}
|
|
|
|
|
|
|
|
return writeSucceed;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2009-10-12 07:56:02 +00:00
|
|
|
}
|
|
|
|
|
2008-01-31 09:17:32 +00:00
|
|
|
|
2009-10-21 07:48:27 +00:00
|
|
|
CompressorInterface * Compressor::Private::chooseCpuCompressor(const CompressionOptions::Private & compressionOptions) const
|
2008-01-30 08:21:55 +00:00
|
|
|
{
|
2010-03-16 22:37:25 +00:00
|
|
|
if (compressionOptions.format == Format_RGB)
|
|
|
|
{
|
|
|
|
return new PixelFormatConverter;
|
|
|
|
}
|
2010-06-24 07:32:17 +00:00
|
|
|
else if (compressionOptions.format == Format_DXT1)
|
|
|
|
{
|
2008-01-30 08:21:55 +00:00
|
|
|
#if defined(HAVE_ATITC)
|
2010-11-03 18:31:16 +00:00
|
|
|
if (compressionOptions.externalCompressor == "ati") return new AtiCompressorDXT1;
|
2010-06-24 07:32:17 +00:00
|
|
|
else
|
2008-01-30 08:21:55 +00:00
|
|
|
#endif
|
2008-11-23 08:59:56 +00:00
|
|
|
|
|
|
|
#if defined(HAVE_SQUISH)
|
2010-11-03 18:31:16 +00:00
|
|
|
if (compressionOptions.externalCompressor == "squish") return new SquishCompressorDXT1;
|
2010-06-24 07:32:17 +00:00
|
|
|
else
|
2008-11-23 08:59:56 +00:00
|
|
|
#endif
|
|
|
|
|
2009-07-06 09:04:29 +00:00
|
|
|
#if defined(HAVE_D3DX)
|
2010-11-03 18:31:16 +00:00
|
|
|
if (compressionOptions.externalCompressor == "d3dx") return new D3DXCompressorDXT1;
|
2010-06-24 07:32:17 +00:00
|
|
|
else
|
2009-07-06 09:04:29 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(HAVE_D3DX)
|
2010-11-03 18:31:16 +00:00
|
|
|
if (compressionOptions.externalCompressor == "stb") return new StbCompressorDXT1;
|
2010-06-24 07:32:17 +00:00
|
|
|
else
|
2009-07-06 09:04:29 +00:00
|
|
|
#endif
|
|
|
|
|
2010-11-03 18:31:16 +00:00
|
|
|
if (compressionOptions.quality == Quality_Fastest)
|
|
|
|
{
|
2010-06-24 07:32:17 +00:00
|
|
|
return new FastCompressorDXT1;
|
|
|
|
}
|
|
|
|
|
2012-04-30 23:03:44 +00:00
|
|
|
return new CompressorDXT1;
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_DXT1a)
|
|
|
|
{
|
|
|
|
if (compressionOptions.quality == Quality_Fastest)
|
|
|
|
{
|
|
|
|
return new FastCompressorDXT1a;
|
|
|
|
}
|
|
|
|
|
2012-04-30 23:03:44 +00:00
|
|
|
return new CompressorDXT1a;
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_DXT1n)
|
|
|
|
{
|
|
|
|
// Not supported.
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_DXT3)
|
|
|
|
{
|
|
|
|
if (compressionOptions.quality == Quality_Fastest)
|
|
|
|
{
|
|
|
|
return new FastCompressorDXT3;
|
|
|
|
}
|
|
|
|
|
2012-04-30 23:03:44 +00:00
|
|
|
return new CompressorDXT3;
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_DXT5)
|
|
|
|
{
|
2009-07-06 09:04:29 +00:00
|
|
|
#if defined(HAVE_ATITC)
|
2010-06-24 07:32:17 +00:00
|
|
|
if (compressionOptions.externalCompressor == "ati") return new AtiCompressorDXT5;
|
|
|
|
else
|
2009-07-06 09:04:29 +00:00
|
|
|
#endif
|
2009-10-21 07:48:27 +00:00
|
|
|
|
2010-11-03 18:31:16 +00:00
|
|
|
if (compressionOptions.quality == Quality_Fastest)
|
|
|
|
{
|
2010-06-24 07:32:17 +00:00
|
|
|
return new FastCompressorDXT5;
|
|
|
|
}
|
|
|
|
|
2012-04-30 23:03:44 +00:00
|
|
|
return new CompressorDXT5;
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_DXT5n)
|
|
|
|
{
|
|
|
|
if (compressionOptions.quality == Quality_Fastest)
|
|
|
|
{
|
|
|
|
return new FastCompressorDXT5n;
|
|
|
|
}
|
|
|
|
|
2012-04-30 23:03:44 +00:00
|
|
|
return new CompressorDXT5n;
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_BC4)
|
|
|
|
{
|
|
|
|
if (compressionOptions.quality == Quality_Fastest || compressionOptions.quality == Quality_Normal)
|
|
|
|
{
|
|
|
|
return new FastCompressorBC4;
|
|
|
|
}
|
|
|
|
|
|
|
|
return new ProductionCompressorBC4;
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_BC5)
|
|
|
|
{
|
|
|
|
if (compressionOptions.quality == Quality_Fastest || compressionOptions.quality == Quality_Normal)
|
|
|
|
{
|
|
|
|
return new FastCompressorBC5;
|
|
|
|
}
|
|
|
|
|
|
|
|
return new ProductionCompressorBC5;
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_CTX1)
|
|
|
|
{
|
|
|
|
// Not supported.
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_BC6)
|
|
|
|
{
|
2013-10-25 17:30:55 +00:00
|
|
|
return new CompressorBC6;
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_BC7)
|
|
|
|
{
|
2013-12-07 02:17:08 +00:00
|
|
|
return new CompressorBC7;
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
2009-10-21 07:48:27 +00:00
|
|
|
|
2010-06-24 07:32:17 +00:00
|
|
|
return NULL;
|
2009-10-21 07:48:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CompressorInterface * Compressor::Private::chooseGpuCompressor(const CompressionOptions::Private & compressionOptions) const
|
|
|
|
{
|
2010-06-24 07:32:17 +00:00
|
|
|
nvDebugCheck(cudaSupported);
|
2009-10-21 07:48:27 +00:00
|
|
|
|
2010-06-24 07:32:17 +00:00
|
|
|
if (compressionOptions.quality == Quality_Fastest)
|
|
|
|
{
|
|
|
|
// Do not use CUDA compressors in fastest quality mode.
|
|
|
|
return NULL;
|
|
|
|
}
|
2009-10-21 07:48:27 +00:00
|
|
|
|
2010-03-16 22:37:25 +00:00
|
|
|
#if defined HAVE_CUDA
|
2010-06-24 07:32:17 +00:00
|
|
|
if (compressionOptions.format == Format_DXT1)
|
|
|
|
{
|
|
|
|
return new CudaCompressorDXT1(*cuda);
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_DXT1a)
|
|
|
|
{
|
2010-11-03 18:31:16 +00:00
|
|
|
//#pragma NV_MESSAGE("TODO: Implement CUDA DXT1a compressor.")
|
2010-06-24 07:32:17 +00:00
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_DXT1n)
|
|
|
|
{
|
|
|
|
// Not supported.
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_DXT3)
|
|
|
|
{
|
|
|
|
//return new CudaCompressorDXT3(*cuda);
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_DXT5)
|
|
|
|
{
|
|
|
|
//return new CudaCompressorDXT5(*cuda);
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_DXT5n)
|
|
|
|
{
|
|
|
|
// @@ Return CUDA compressor.
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_BC4)
|
|
|
|
{
|
|
|
|
// Not supported.
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_BC5)
|
|
|
|
{
|
|
|
|
// Not supported.
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_CTX1)
|
|
|
|
{
|
|
|
|
// @@ Return CUDA compressor.
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_BC6)
|
|
|
|
{
|
|
|
|
// Not supported.
|
|
|
|
}
|
|
|
|
else if (compressionOptions.format == Format_BC7)
|
|
|
|
{
|
|
|
|
// Not supported.
|
|
|
|
}
|
2010-03-16 22:37:25 +00:00
|
|
|
#endif // defined HAVE_CUDA
|
2009-10-21 07:48:27 +00:00
|
|
|
|
2010-06-24 07:32:17 +00:00
|
|
|
return NULL;
|
2009-10-21 07:48:27 +00:00
|
|
|
}
|