Repair C wrapper.

Fix + Improve C# / .NET wrapper.
Add an XNA content processor, this will allow texture tools to be used as part of an XNA project.
2.0
dblack@fastmail.fm 14 years ago
parent 3c559666b0
commit b24e3bbcf2

@ -134,23 +134,45 @@ namespace Nvidia.TextureTools
/// </summary>
public enum Error
{
Unknown,
InvalidInput,
UserInterruption,
UnsupportedFeature,
UnsupportedFeature,
CudaError,
Unknown,
FileOpen,
FileOpen,
FileWrite,
}
#endregion
#endregion
#region public class InputOptions
/// <summary>
#endregion
#region Exception Class
public class TextureToolsException : ApplicationException
{
Error errorCode = Error.Unknown;
public Error ErrorCode
{
get { return errorCode; }
}
public TextureToolsException(Error errorCode) : base(Compressor.ErrorString(errorCode))
{
this.errorCode = errorCode;
}
}
#endregion
#region public class InputOptions
/// <summary>
/// Input options.
/// </summary>
public class InputOptions
public class InputOptions : IDisposable
{
#region Bindings
[DllImport("nvtt"), SuppressUnmanagedCodeSecurity]
@ -223,10 +245,7 @@ namespace Nvidia.TextureTools
{
options = nvttCreateInputOptions();
}
~InputOptions()
{
nvttDestroyInputOptions(options);
}
public void SetTextureLayout(TextureType type, int w, int h, int d)
{
@ -237,6 +256,22 @@ namespace Nvidia.TextureTools
nvttResetInputOptionsTextureLayout(options);
}
public void SetMipmapData(byte[] data, int width, int height, int depth, int face, int mipmap)
{
//unsafe() would be cleaner, but that would require compiling with the unsafe compiler option....
GCHandle gcHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
try
{
SetMipmapData(gcHandle.AddrOfPinnedObject(), width, height, depth, face, mipmap);
}
finally
{
gcHandle.Free();
}
}
public void SetMipmapData(IntPtr data, int width, int height, int depth, int face, int mipmap)
{
nvttSetInputOptionsMipmapData(options, data, width, height, depth, face, mipmap);
@ -326,14 +361,39 @@ namespace Nvidia.TextureTools
{
nvttSetInputOptionsRoundMode(options, mode);
}
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (options != IntPtr.Zero)
{
nvttDestroyInputOptions(options);
options = IntPtr.Zero;
}
}
~InputOptions()
{
Dispose(false);
}
#endregion
}
#endregion
#region public class CompressionOptions
/// <summary>
/// Compression options.
/// </summary>
public class CompressionOptions
public class CompressionOptions : IDisposable
{
#region Bindings
[DllImport("nvtt"), SuppressUnmanagedCodeSecurity]
@ -356,6 +416,7 @@ namespace Nvidia.TextureTools
[DllImport("nvtt"), SuppressUnmanagedCodeSecurity]
private extern static void nvttSetCompressionOptionsQuantization(IntPtr compressionOptions, bool colorDithering, bool alphaDithering, bool binaryAlpha, int alphaThreshold);
#endregion
internal IntPtr options;
@ -364,10 +425,6 @@ namespace Nvidia.TextureTools
{
options = nvttCreateCompressionOptions();
}
~CompressionOptions()
{
nvttDestroyCompressionOptions(options);
}
public void SetFormat(Format format)
{
@ -403,23 +460,104 @@ namespace Nvidia.TextureTools
{
nvttSetCompressionOptionsQuantization(options, colorDithering, alphaDithering, binaryAlpha, alphaThreshold);
}
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (options != IntPtr.Zero)
{
nvttDestroyCompressionOptions(options);
options = IntPtr.Zero;
}
}
~CompressionOptions()
{
Dispose(false);
}
#endregion
}
#endregion
#region public class OutputOptions
public interface IOutputHandler
{
void BeginImage(int size, int width, int height, int depth, int face, int miplevel);
void WriteDataUnsafe(IntPtr data, int size);
}
/*
* This class provides a nicer interface for the output handler by taking care of the marshalling of the image data.
* However the IOutputHandler interface is still provided to allow the user to do this themselves to avoid the
* additional copying and memory allocations.
*/
public abstract class OutputHandlerBase : IOutputHandler
{
private byte[] tempData;
protected OutputHandlerBase()
{
}
protected abstract void BeginImage(int size, int width, int height, int depth, int face, int miplevel);
protected abstract void WriteData(byte[] dataBuffer, int startIndex, int count);
#region IOutputHandler Members
void IOutputHandler.BeginImage(int size, int width, int height, int depth, int face, int miplevel)
{
BeginImage(size, width, height, depth, face, miplevel);
}
void IOutputHandler.WriteDataUnsafe(IntPtr data, int size)
{
if ((tempData == null) || (size > tempData.Length))
tempData = new byte[size];
Marshal.Copy(data, tempData, 0, size);
// Zero additional buffer elements to to aid reproducability of bugs.
Array.Clear(tempData, size, tempData.Length - size);
WriteData(tempData, 0, size);
}
#endregion
}
/// <summary>
/// Output options.
/// </summary>
public class OutputOptions
public class OutputOptions : IDisposable
{
#region Delegates
public delegate void ErrorHandler(Error error);
private delegate void WriteDataDelegate(IntPtr data, int size);
private delegate void ImageDelegate(int size, int width, int height, int depth, int face, int miplevel);
#region Delegates
private delegate void InternalErrorHandlerDelegate(Error error);
private delegate void WriteDataDelegate(IntPtr data, int size);
private delegate void ImageDelegate(int size, int width, int height, int depth, int face, int miplevel);
#endregion
#region Bindings
[DllImport("nvtt"), SuppressUnmanagedCodeSecurity]
private Error lastErrorCode = Error.Unknown;
internal Error LastErrorCode
{
get { return lastErrorCode; }
}
#region Bindings
[DllImport("nvtt"), SuppressUnmanagedCodeSecurity]
private extern static IntPtr nvttCreateOutputOptions();
[DllImport("nvtt"), SuppressUnmanagedCodeSecurity]
@ -429,51 +567,121 @@ namespace Nvidia.TextureTools
private extern static void nvttSetOutputOptionsFileName(IntPtr outputOptions, string fileName);
[DllImport("nvtt"), SuppressUnmanagedCodeSecurity]
private extern static void nvttSetOutputOptionsErrorHandler(IntPtr outputOptions, ErrorHandler errorHandler);
private void ErrorCallback(Error error)
{
if (Error != null) Error(error);
}
private extern static void nvttSetOutputOptionsErrorHandler(IntPtr outputOptions, InternalErrorHandlerDelegate errorHandler);
[DllImport("nvtt"), SuppressUnmanagedCodeSecurity]
private extern static void nvttSetOutputOptionsOutputHeader(IntPtr outputOptions, bool b);
//[DllImport("nvtt"), SuppressUnmanagedCodeSecurity]
//private extern static void nvttSetOutputOptionsOutputHandler(IntPtr outputOptions, WriteDataDelegate writeData, ImageDelegate image);
[DllImport("nvtt"), SuppressUnmanagedCodeSecurity]
private extern static void nvttSetOutputOptionsOutputHandler(IntPtr outputOptions, IntPtr writeData, IntPtr image);
#endregion
internal IntPtr options;
//Note: these references are used to prevent garbage collection of the delegates(and hence class) if they are
//only referenced from unmanaged land.
private WriteDataDelegate writeDataDelegate;
private ImageDelegate beginImageDelegate;
private IOutputHandler currentOutputHandler;
public OutputOptions()
{
options = nvttCreateOutputOptions();
nvttSetOutputOptionsErrorHandler(options, new ErrorHandler(ErrorCallback));
}
~OutputOptions()
{
nvttDestroyOutputOptions(options);
nvttSetOutputOptionsErrorHandler(options, ErrorCallback);
}
public void SetFileName(string fileName)
{
nvttSetOutputOptionsFileName(options, fileName);
}
public event ErrorHandler Error;
public void SetOutputHeader(bool b)
{
nvttSetOutputOptionsOutputHeader(options, b);
}
// @@ Add OutputHandler interface.
}
public void SetOutputHandler(IOutputHandler outputHandler)
{
if (outputHandler != null)
{
//We need to store a ref in order to prevent garbage collection.
WriteDataDelegate tmpWriteDataDelegate = new WriteDataDelegate(WriteDataCallback);
ImageDelegate tmpBeginImageDelegate = new ImageDelegate(ImageCallback);
IntPtr ptrWriteData = Marshal.GetFunctionPointerForDelegate(tmpWriteDataDelegate);
IntPtr ptrBeginImage = Marshal.GetFunctionPointerForDelegate(tmpBeginImageDelegate);
nvttSetOutputOptionsOutputHandler(options, ptrWriteData, ptrBeginImage);
writeDataDelegate = tmpWriteDataDelegate;
beginImageDelegate = tmpBeginImageDelegate;
currentOutputHandler = outputHandler;
}
else
{
nvttSetOutputOptionsOutputHandler(options, IntPtr.Zero, IntPtr.Zero);
writeDataDelegate = null;
beginImageDelegate = null;
currentOutputHandler = null;
}
}
private void ErrorCallback(Error error)
{
lastErrorCode = error;
}
private void WriteDataCallback(IntPtr data, int size)
{
if (currentOutputHandler != null) currentOutputHandler.WriteDataUnsafe(data, size);
}
private void ImageCallback(int size, int width, int height, int depth, int face, int miplevel)
{
if (currentOutputHandler != null) currentOutputHandler.BeginImage(size, width, height, depth, face, miplevel);
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (options != IntPtr.Zero)
{
nvttDestroyOutputOptions(options);
options = IntPtr.Zero;
}
writeDataDelegate = null;
beginImageDelegate = null;
currentOutputHandler = null;
}
~OutputOptions()
{
Dispose(false);
}
#endregion
}
#endregion
#region public static class Compressor
public class Compressor
#region public class Compressor
public class Compressor : IDisposable
{
#region Bindings
[DllImport("nvtt"), SuppressUnmanagedCodeSecurity]
@ -490,6 +698,12 @@ namespace Nvidia.TextureTools
[DllImport("nvtt"), SuppressUnmanagedCodeSecurity]
private static extern IntPtr nvttErrorString(Error error);
[DllImport("nvtt"), SuppressUnmanagedCodeSecurity]
private extern static uint nvttVersion();
[DllImport("nvtt"), SuppressUnmanagedCodeSecurity]
private extern static void nvttEnableCudaCompression(IntPtr compressor, bool enable);
#endregion
@ -499,15 +713,14 @@ namespace Nvidia.TextureTools
{
compressor = nvttCreateCompressor();
}
~Compressor()
public void Compress(InputOptions input, CompressionOptions compression, OutputOptions output)
{
nvttDestroyCompressor(compressor);
}
public bool Compress(InputOptions input, CompressionOptions compression, OutputOptions output)
{
return nvttCompress(compressor, input.options, compression.options, output.options);
if (!nvttCompress(compressor, input.options, compression.options, output.options))
{
//An error occured, use the last error registered.
throw new TextureToolsException(output.LastErrorCode);
}
}
public int EstimateSize(InputOptions input, CompressionOptions compression)
@ -520,7 +733,138 @@ namespace Nvidia.TextureTools
return Marshal.PtrToStringAnsi(nvttErrorString(error));
}
}
public static uint Version()
{
return nvttVersion();
}
public void SetEnableCuda(bool enableCuda)
{
nvttEnableCudaCompression(compressor, enableCuda);
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (compressor != IntPtr.Zero)
{
nvttDestroyCompressor(compressor);
compressor = IntPtr.Zero;
}
}
~Compressor()
{
Dispose(false);
}
#endregion
}
#endregion
#region public class CompressorOptionsBundle
/*
* We provide a class which combines all the objects, this simplifies usage such as:
*
* using(CompressorOptionsBundle compressor = new CompressorOptionsBundle())
* {
* compressor.InputOptions.SetMipmapData(...);
* ...
* }
*
* Making it easy to write exception safe code etc.
*/
public class CompressorOptionsBundle : IDisposable
{
InputOptions inputOptions;
CompressionOptions compressionOptions;
OutputOptions outputOptions;
Compressor compressor;
public InputOptions InputOptions
{
get { return inputOptions; }
}
public CompressionOptions CompressionOptions
{
get { return compressionOptions; }
}
public OutputOptions OutputOptions
{
get { return outputOptions; }
}
public Compressor Compressor
{
get { return compressor; }
}
public CompressorOptionsBundle()
{
inputOptions = new InputOptions();
compressionOptions = new CompressionOptions();
outputOptions = new OutputOptions();
compressor = new Compressor();
}
public void Compress()
{
compressor.Compress(inputOptions, compressionOptions, outputOptions);
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (inputOptions != null)
{
inputOptions.Dispose();
inputOptions = null;
}
if (compressionOptions != null)
{
compressionOptions.Dispose();
compressionOptions = null;
}
if (outputOptions != null)
{
outputOptions.Dispose();
outputOptions = null;
}
if (compressor != null)
{
compressor.Dispose();
compressor = null;
}
}
}
#endregion
}
#endregion
} // Nvidia.TextureTools namespace

@ -0,0 +1,482 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;
using Nvidia.TextureTools;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.IO;
namespace NvidiaTextureToolsProcessor
{
[ContentProcessor(DisplayName = "NvidiaTextureProcessor")]
public class NvidiaTextureProcessor : ContentProcessor<TextureContent, TextureContent>
{
// Note: We dont expose all of Texture Tools formats since XNA does not support the custom formats(eg ATI1 / ATI2 etc).
// Plus we can use some friendlier/more consistant names
public enum TextureOutputFormat
{
Colour,
Normals,
DXT1,
DXT1a, // With 1 bit alpha
DXT3,
DXT5,
DXT5n, // Compressed Normals HILO: R=1, G=y, B=0, A=x
}
bool convertToNormalMap = false;
bool generateMipmaps = true;
int maxMipLevel = -1;
float inputGamma = 2.2f;
float outputGamma = 2.2f;
TextureOutputFormat textureFormat = TextureOutputFormat.DXT1;
Quality quality = Quality.Normal;
WrapMode wrapMode = WrapMode.Mirror;
MipmapFilter mipMapFilter = MipmapFilter.Box;
RoundMode roundMode = RoundMode.None;
AlphaMode alphaMode = AlphaMode.None;
bool enableCuda = true;
[DisplayName("Convert To Normal Map")]
[DefaultValue(false)]
[Description("When true the input data is converted from colour/height data into a normal map if the output is a normal map.")]
[Category("Input")]
public bool ConvertToNormalMap
{
get { return convertToNormalMap; }
set { convertToNormalMap = value; }
}
[DisplayName("Generate Mip Maps")]
[DefaultValue(true)]
[Description("When set to true the processor will generate mip maps")]
[Category("Mip Mapping")]
public bool GenerateMipmaps
{
get { return generateMipmaps; }
set { generateMipmaps = value; }
}
[DisplayName("Max Mip Map Level")]
[DefaultValue(-1)]
[Description("Setting the max mip map level allows partial mip map chains to be generated. -1 generates all levels if mip map generation is enabled.")]
[Category("Mip Mapping")]
public int MaxMipMapLevel
{
get { return maxMipLevel; }
set { maxMipLevel = value; }
}
[DisplayName("Input Gamma")]
[DefaultValue(2.2f)]
[Description("The gamma conversion performed before mip map generation, for best results mip maps should be generated in linear colour space.")]
[Category("Gamma")]
public float InputGamma
{
get { return inputGamma; }
set { inputGamma = value; }
}
[DisplayName("Output Gamma")]
[DefaultValue(2.2f)]
[Description("The gamma conversion applied during output. In general this should be left at 2.2 for LDR images.")]
[Category("Gamma")]
public float OutputGamma
{
get { return outputGamma; }
set { outputGamma = value; }
}
[DisplayName("Texture Output Format")]
[DefaultValue(TextureOutputFormat.DXT1)]
[Description("The format which the processor generates, Color means no compression, DXT1 if useful for textures with no alpha, DXT5 for textures with alpha and DXT5n for normal maps.")]
[Category("Output")]
public TextureOutputFormat TextureFormat
{
get { return textureFormat; }
set { textureFormat = value; }
}
[DisplayName("Compression Quality")]
[DefaultValue(Quality.Normal)]
[Description("Specifies the amount of time the processor will spend trying to find the best quality compression. Highest should only be used for testing as it uses a brute force approach.")]
[Category("Output")]
public Quality Quality
{
get { return quality; }
set { quality = value; }
}
[DisplayName("Wrap Mode")]
[DefaultValue(WrapMode.Mirror)]
[Description("Specifying the wrap mode used for the texture can sometimes improve the quality of filtering. In general Mirror should give good results.")]
[Category("Input")]
public WrapMode WrapMode
{
get { return wrapMode; }
set { wrapMode = value; }
}
[DisplayName("Mip Map Filter")]
[DefaultValue(MipmapFilter.Box)]
[Description("Specifies which filter to use for down sampling mip maps. Box generally gives good results, Triangle will often appear blurry and Kaiser is the slowest but best quality.")]
[Category("Mip Mapping")]
public MipmapFilter MipMapFilter
{
get { return mipMapFilter; }
set { mipMapFilter = value; }
}
[DisplayName("Texture Size Rounding Mode")]
[DefaultValue(RoundMode.None)]
[Description("Setting the rounding mode allows the texture to be resized to a power of 2, often needed for less capable hardware.")]
[Category("Input")]
public RoundMode TextureRoundingMode
{
get { return roundMode; }
set { roundMode = value; }
}
[DisplayName("Alpha Mode")]
[DefaultValue(AlphaMode.None)]
[Description("Setting the alpha mode allows improved quality when generating mip maps.")]
[Category("Input")]
public AlphaMode AlphaMode
{
get { return alphaMode; }
set { alphaMode = value; }
}
[DisplayName("Enable Cuda")]
[DefaultValue(true)]
[Description("When true Cuda will be utilised if available.")]
[Category("Compressor")]
public bool EnableCuda
{
get { return enableCuda; }
set { enableCuda = value; }
}
public override TextureContent Process(TextureContent input, ContentProcessorContext context)
{
//System.Diagnostics.Debugger.Launch();
input.Validate();
try
{
using (CompressorOptionsBundle compressor = new CompressorOptionsBundle())
{
compressor.InputOptions.ResetTextureLayout();
TextureType textureType = FindTextureType(input);
/*
* Set options
*/
compressor.InputOptions.SetTextureLayout(textureType, input.Faces[0][0].Width, input.Faces[0][0].Height, 1);
compressor.InputOptions.SetFormat(InputFormat.BGRA_8UB);
compressor.InputOptions.SetAlphaMode(AlphaMode);
compressor.InputOptions.SetMipmapFilter(MipMapFilter);
compressor.InputOptions.SetMipmapGeneration(GenerateMipmaps, MaxMipMapLevel);
compressor.InputOptions.SetRoundMode(TextureRoundingMode);
compressor.InputOptions.SetWrapMode(WrapMode);
compressor.InputOptions.SetGamma(InputGamma, OutputGamma);
compressor.InputOptions.SetNormalizeMipmaps(false);
compressor.InputOptions.SetNormalMap(false);
compressor.InputOptions.SetConvertToNormalMap(false);
compressor.CompressionOptions.SetQuality(Quality);
GeneralOutputHandler outputHandler;
switch (TextureFormat)
{
case TextureOutputFormat.Colour:
compressor.CompressionOptions.SetFormat(Format.RGBA);
outputHandler = new PixelOutputHandler<Color>(textureType);
break;
case TextureOutputFormat.Normals:
compressor.CompressionOptions.SetFormat(Format.RGBA);
outputHandler = new PixelOutputHandler<Color>(textureType);
compressor.InputOptions.SetNormalizeMipmaps(true);
compressor.InputOptions.SetNormalMap(true);
compressor.InputOptions.SetConvertToNormalMap(ConvertToNormalMap);
compressor.InputOptions.SetGamma(1.0f, 1.0f);
break;
case TextureOutputFormat.DXT1:
compressor.CompressionOptions.SetFormat(Format.DXT1);
outputHandler = new Dxt1OutputHandler(textureType);
break;
case TextureOutputFormat.DXT1a:
compressor.CompressionOptions.SetFormat(Format.DXT1a);
outputHandler = new Dxt1OutputHandler(textureType);
break;
case TextureOutputFormat.DXT3:
compressor.CompressionOptions.SetFormat(Format.DXT3);
outputHandler = new Dxt3OutputHandler(textureType);
break;
case TextureOutputFormat.DXT5:
compressor.CompressionOptions.SetFormat(Format.DXT5);
outputHandler = new Dxt5OutputHandler(textureType);
break;
case TextureOutputFormat.DXT5n:
//FIXME: We force fastest quality since the normal compression mode is _very_ slow.
compressor.CompressionOptions.SetQuality(Quality.Fastest);
compressor.CompressionOptions.SetFormat(Format.DXT5n);
compressor.InputOptions.SetNormalizeMipmaps(true);
compressor.InputOptions.SetNormalMap(true);
compressor.InputOptions.SetConvertToNormalMap(ConvertToNormalMap);
compressor.InputOptions.SetGamma(1.0f, 1.0f);
outputHandler = new Dxt5OutputHandler(textureType);
break;
default:
throw new NotSupportedException("Unknown texture output format: " + TextureFormat);
}
/*
* Set input data
*/
//TODO: Use a float format when texture tools support it.
input.ConvertBitmapType(typeof(PixelBitmapContent<Color>));
for (int i = 0; i < input.Faces.Count; i++)
{
MipmapChain mipChain = input.Faces[i];
for (int j = 0; j < mipChain.Count; j++)
{
BitmapContent bitmap = mipChain[j];
byte[] bitmapData = bitmap.GetPixelData();
//FIXME: When we move to XNA 4 the layout of Color will change, hence we need to swizzle the input.
compressor.InputOptions.SetMipmapData(bitmapData, bitmap.Width, bitmap.Height, 1, i, j);
}
}
/*
* Setup output
*/
compressor.OutputOptions.SetOutputHandler(outputHandler);
compressor.OutputOptions.SetOutputHeader(false);
/*
* Go!
*/
compressor.Compressor.SetEnableCuda(EnableCuda);
compressor.Compress();
/*
* Check the output makes sense.
*/
outputHandler.OutputTextureContent.Validate();
return outputHandler.OutputTextureContent;
}
}
catch (TextureToolsException ttexcept)
{
throw ConvertException(ttexcept);
}
}
private TextureType FindTextureType(TextureContent input)
{
if (input is Texture2DContent)
return TextureType.Texture2D;
else if (input is TextureCubeContent)
return TextureType.TextureCube;
else
throw new InvalidContentException("Invalid texture type, cube maps are not supported", input.Identity);
}
private Exception ConvertException(TextureToolsException ttexcept)
{
switch (ttexcept.ErrorCode)
{
case Error.UnsupportedFeature:
return new NotSupportedException("Attempt to use a unsupported feature of NVIDIA Texture Tools",ttexcept);
case Error.InvalidInput:
return new InvalidContentException("Invalid input to NVIDIA texture tools", ttexcept);
case Error.CudaError:
case Error.Unknown:
return new InvalidOperationException("NVIDIA Texture Tools returned the following error: " + ttexcept.Message, ttexcept);
case Error.FileOpen:
case Error.FileWrite:
return new IOException("NVIDIA Texture Tools returned the following error: " + ttexcept.Message, ttexcept);
default:
return new InvalidOperationException("NVIDIA Texture Tools returned an unknown error: " + ttexcept.Message, ttexcept);
}
}
private class Dxt1OutputHandler : GeneralOutputHandler
{
public Dxt1OutputHandler(TextureType textureType) : base(textureType)
{
}
protected override BitmapContent CreateBitmapContent(int width, int height)
{
return new Dxt1BitmapContent(width, height);
}
}
private class Dxt3OutputHandler : GeneralOutputHandler
{
public Dxt3OutputHandler(TextureType textureType)
: base(textureType)
{
}
protected override BitmapContent CreateBitmapContent(int width, int height)
{
return new Dxt3BitmapContent(width, height);
}
}
private class Dxt5OutputHandler : GeneralOutputHandler
{
public Dxt5OutputHandler(TextureType textureType)
: base(textureType)
{
}
protected override BitmapContent CreateBitmapContent(int width, int height)
{
return new Dxt5BitmapContent(width, height);
}
}
private class PixelOutputHandler<T> : GeneralOutputHandler
where T : struct, System.IEquatable<T>
{
public PixelOutputHandler(TextureType textureType)
: base(textureType)
{
}
protected override BitmapContent CreateBitmapContent(int width, int height)
{
return new PixelBitmapContent<T>(width, height);
}
}
private abstract class GeneralOutputHandler : OutputHandlerBase
{
TextureContent outputTextureContent;
byte[] tempBitmapData;
int dataWidth = -1;
int dataHeight = -1;
int dataSize = -1;
int faceIndex = -1;
int mipIndex = -1;
int dataIndex = 0;
public TextureContent OutputTextureContent
{
get
{
CommitLevel();
return outputTextureContent;
}
}
protected GeneralOutputHandler(TextureType textureType)
{
switch (textureType)
{
case TextureType.Texture2D:
outputTextureContent = new Texture2DContent();
break;
case TextureType.TextureCube:
outputTextureContent = new TextureCubeContent();
break;
default:
throw new NotSupportedException("Unknown texture type: " + textureType);
}
}
protected override void BeginImage(int size, int width, int height, int depth, int face, int miplevel)
{
CommitLevel();
dataIndex = 0;
mipIndex = miplevel;
faceIndex = face;
dataWidth = width;
dataHeight = height;
dataSize = size;
tempBitmapData = new byte[size];
}
protected override void WriteData(byte[] dataBuffer, int startIndex, int count)
{
Array.Copy(dataBuffer, startIndex, tempBitmapData, dataIndex, count);
dataIndex += count;
}
protected abstract BitmapContent CreateBitmapContent(int width, int height);
private void CommitLevel()
{
if (faceIndex >= 0)
{
BitmapContent newBitmap = CreateBitmapContent(dataWidth, dataHeight);
newBitmap.SetPixelData(tempBitmapData);
outputTextureContent.Faces[faceIndex].Add(newBitmap);
dataSize = -1;
dataWidth = dataHeight = -1;
faceIndex = -1;
mipIndex = -1;
dataIndex = 0;
}
}
}
}
}

@ -0,0 +1,122 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<ProjectGuid>{F4446AE2-B5E1-4D17-B33C-275A6770FD50}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>NvidiaTextureToolsProcessor</RootNamespace>
<AssemblyName>NvidiaTextureToolsProcessor</AssemblyName>
<XnaFrameworkVersion>v3.1</XnaFrameworkVersion>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<XnaPlatform>Windows</XnaPlatform>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<XnaPlatform>Windows</XnaPlatform>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|Xbox 360' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Xbox 360\Debug</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<PlatformTarget>x86</PlatformTarget>
<XnaPlatform>Xbox 360</XnaPlatform>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|Xbox 360' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Xbox 360\Release</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<PlatformTarget>x86</PlatformTarget>
<XnaPlatform>Xbox 360</XnaPlatform>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|Zune' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Zune\Debug</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<PlatformTarget>x86</PlatformTarget>
<XnaPlatform>Zune</XnaPlatform>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|Zune' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Zune\Release</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<PlatformTarget>x86</PlatformTarget>
<XnaPlatform>Zune</XnaPlatform>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Xna.Framework, Version=3.1.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=x86">
<Private>False</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="Microsoft.Xna.Framework.Game, Version=3.1.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=MSIL">
<Private>False</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="Microsoft.Xna.Framework.Content.Pipeline, Version=3.1.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d, processorArchitecture=x86">
<Private>False</Private>
<SpecificVersion>true</SpecificVersion>
</Reference>
<Reference Include="System">
<Private>False</Private>
</Reference>
<Reference Include="System.Xml">
<Private>False</Private>
</Reference>
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Nvidia.TextureTools\TextureTools.cs">
<Link>TextureTools.cs</Link>
</Compile>
<Compile Include="NvidiaTextureProcessor.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\Microsoft.Xna.GameStudio.ContentPipelineExtensions.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

@ -0,0 +1,32 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C# Express 2008
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NvidiaTextureToolsProcessor", "NvidiaTextureToolsProcessor.csproj", "{F4446AE2-B5E1-4D17-B33C-275A6770FD50}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Debug|Xbox 360 = Debug|Xbox 360
Debug|Zune = Debug|Zune
Release|x86 = Release|x86
Release|Xbox 360 = Release|Xbox 360
Release|Zune = Release|Zune
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F4446AE2-B5E1-4D17-B33C-275A6770FD50}.Debug|x86.ActiveCfg = Debug|x86
{F4446AE2-B5E1-4D17-B33C-275A6770FD50}.Debug|x86.Build.0 = Debug|x86
{F4446AE2-B5E1-4D17-B33C-275A6770FD50}.Debug|Xbox 360.ActiveCfg = Debug|Xbox 360
{F4446AE2-B5E1-4D17-B33C-275A6770FD50}.Debug|Xbox 360.Build.0 = Debug|Xbox 360
{F4446AE2-B5E1-4D17-B33C-275A6770FD50}.Debug|Zune.ActiveCfg = Debug|Zune
{F4446AE2-B5E1-4D17-B33C-275A6770FD50}.Debug|Zune.Build.0 = Debug|Zune
{F4446AE2-B5E1-4D17-B33C-275A6770FD50}.Release|x86.ActiveCfg = Release|x86
{F4446AE2-B5E1-4D17-B33C-275A6770FD50}.Release|x86.Build.0 = Release|x86
{F4446AE2-B5E1-4D17-B33C-275A6770FD50}.Release|Xbox 360.ActiveCfg = Release|Xbox 360
{F4446AE2-B5E1-4D17-B33C-275A6770FD50}.Release|Xbox 360.Build.0 = Release|Xbox 360
{F4446AE2-B5E1-4D17-B33C-275A6770FD50}.Release|Zune.ActiveCfg = Release|Zune
{F4446AE2-B5E1-4D17-B33C-275A6770FD50}.Release|Zune.Build.0 = Release|Zune
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

@ -0,0 +1,33 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("NvidiaTextureToolsProcessor")]
[assembly: AssemblyDescription("An XNA Content Processor for use with GameStudio 3.1")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NvidiaTextureToolsProcessor")]
[assembly: AssemblyCopyright("Copyright © 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("6c0942a6-4e6a-411b-9275-d2676f9720d3")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

@ -28,6 +28,7 @@ using namespace nvtt;
OutputOptions::OutputOptions() : m(*new OutputOptions::Private())
{
m.cWrapperProxy = NULL;
reset();
}
@ -72,7 +73,6 @@ void OutputOptions::setOutputHeader(bool outputHeader)
m.outputHeader = outputHeader;
}
bool OutputOptions::Private::openFile() const
{
if (!fileName.isNull())

@ -65,6 +65,8 @@ namespace nvtt
ErrorHandler * errorHandler;
bool outputHeader;
void * cWrapperProxy;
bool openFile() const;
void closeFile() const;
};

@ -1,7 +1,49 @@
#include <stdio.h> //For NULL...
#include "nvtt.h"
#include "nvtt_wrapper.h"
#include "OutputOptions.h"
namespace nvttCWrap
{
//Simple class to re-route calls to the C++ interfaces to C functions
struct HandlerProxy : public nvtt::ErrorHandler, public nvtt::OutputHandler
{
public:
HandlerProxy()
{
errorFunc = NULL;
outputFunc = NULL;
imageFunc = NULL;
}
virtual void error(nvtt::Error e)
{
if(errorFunc != NULL)
errorFunc((NvttError)e);
}
virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel)
{
if(imageFunc != NULL)
imageFunc(size, width, height, depth, face, miplevel);
}
virtual bool writeData(const void * data, int size)
{
if(outputFunc != NULL)
return (outputFunc(data, size) != NVTT_False);
else
return true; //Just say we succeed anyway... despite nothing being done, in case the user only set the beginImage() func.
}
nvttErrorHandler errorFunc;
nvttOutputHandler outputFunc;
nvttImageHandler imageFunc;
};
}
// InputOptions class.
NvttInputOptions * nvttCreateInputOptions()
@ -110,6 +152,7 @@ void nvttSetInputOptionsRoundMode(NvttInputOptions * inputOptions, NvttRoundMode
}
// CompressionOptions class.
NvttCompressionOptions * nvttCreateCompressionOptions()
{
@ -136,11 +179,6 @@ void nvttSetCompressionOptionsColorWeights(NvttCompressionOptions * compressionO
compressionOptions->setColorWeights(red, green, blue, alpha);
}
/*void nvttEnableCompressionOptionsCudaCompression(NvttCompressionOptions * compressionOptions, NvttBoolean enable)
{
compressionOptions->enableCudaCompression(enable != NVTT_False);
}*/
void nvttSetCompressionOptionsPixelFormat(NvttCompressionOptions * compressionOptions, unsigned int bitcount, unsigned int rmask, unsigned int gmask, unsigned int bmask, unsigned int amask)
{
compressionOptions->setPixelFormat(bitcount, rmask, gmask, bmask, amask);
@ -151,16 +189,23 @@ void nvttSetCompressionOptionsQuantization(NvttCompressionOptions * compressionO
compressionOptions->setQuantization(colorDithering != NVTT_False, alphaDithering != NVTT_False, binaryAlpha != NVTT_False, alphaThreshold);
}
// OutputOptions class.
NvttOutputOptions * nvttCreateOutputOptions()
{
return new nvtt::OutputOptions();
nvtt::OutputOptions * outputOptions = new nvtt::OutputOptions();
nvttCWrap::HandlerProxy * handlerProxy = new nvttCWrap::HandlerProxy();
outputOptions->m.cWrapperProxy = handlerProxy;
return outputOptions;
}
void nvttDestroyOutputOptions(NvttOutputOptions * outputOptions)
{
nvttCWrap::HandlerProxy * handlerProxy = (nvttCWrap::HandlerProxy *)outputOptions->m.cWrapperProxy;
delete outputOptions;
delete handlerProxy;
}
void nvttSetOutputOptionsFileName(NvttOutputOptions * outputOptions, const char * fileName)
@ -172,19 +217,45 @@ void nvttSetOutputOptionsOutputHeader(NvttOutputOptions * outputOptions, NvttBoo
{
outputOptions->setOutputHeader(b != NVTT_False);
}
/*
void nvttSetOutputOptionsErrorHandler(NvttOutputOptions * outputOptions, nvttErrorHandler errorHandler)
{
outputOptions->setErrorHandler(errorHandler);
nvttCWrap::HandlerProxy * handlerProxy = (nvttCWrap::HandlerProxy *)outputOptions->m.cWrapperProxy;
handlerProxy->errorFunc = errorHandler;
if(errorHandler == NULL)
outputOptions->setErrorHandler(NULL);
else
outputOptions->setErrorHandler(handlerProxy);
}
void nvttSetOutputOptionsOutputHandler(NvttOutputOptions * outputOptions, nvttOutputHandler outputHandler, nvttImageHandler imageHandler)
{
nvttCWrap::HandlerProxy * handlerProxy = (nvttCWrap::HandlerProxy *)outputOptions->m.cWrapperProxy;
handlerProxy->outputFunc = outputHandler;
handlerProxy->imageFunc = imageHandler;
if((outputHandler == NULL) && (imageHandler == NULL))
outputOptions->setOutputHandler(NULL);
else
outputOptions->setOutputHandler(handlerProxy);
}
*/
// Compressor class.
NvttCompressor * nvttCreateCompressor()
{
return new nvtt::Compressor();
}
void nvttDestroyCompressor(NvttCompressor * compressor)
{
delete compressor;
}
NvttBoolean nvttCompress(const NvttCompressor * compressor, const NvttInputOptions * inputOptions, const NvttCompressionOptions * compressionOptions, const NvttOutputOptions * outputOptions)
{
return (NvttBoolean)compressor->process(*inputOptions, *compressionOptions, *outputOptions);
@ -195,6 +266,11 @@ int nvttEstimateSize(const NvttCompressor * compressor, const NvttInputOptions *
return compressor->estimateSize(*inputOptions, *compressionOptions);
}
void nvttEnableCudaCompression(NvttCompressor * compressor, NvttBoolean enable)
{
compressor->enableCudaAcceleration(enable != NVTT_False);
}
// Global functions.
const char * nvttErrorString(NvttError e)

@ -149,11 +149,12 @@ typedef enum
typedef enum
{
NVTT_Error_Unknown,
NVTT_Error_InvalidInput,
NVTT_Error_UserInterruption,
NVTT_Error_UnsupportedFeature,
NVTT_Error_CudaError,
NVTT_Error_Unknown,
NVTT_Error_FileOpen,
NVTT_Error_FileWrite,
} NvttError;
@ -170,9 +171,9 @@ extern "C" {
#endif
// Callbacks
//typedef void (* nvttErrorHandler)(NvttError e);
//typedef void (* nvttOutputHandler)(const void * data, int size);
//typedef void (* nvttImageHandler)(int size, int width, int height, int depth, int face, int miplevel);
typedef void (* nvttErrorHandler)(NvttError e);
typedef NvttBoolean (* nvttOutputHandler)(const void * data, int size);
typedef void (* nvttImageHandler)(int size, int width, int height, int depth, int face, int miplevel);
// InputOptions class.
@ -199,7 +200,6 @@ NVTT_API void nvttSetInputOptionsLinearTransform(NvttInputOptions * inputOptions
NVTT_API void nvttSetInputOptionsMaxExtents(NvttInputOptions * inputOptions, int dim);
NVTT_API void nvttSetInputOptionsRoundMode(NvttInputOptions * inputOptions, NvttRoundMode mode);
// CompressionOptions class.
NVTT_API NvttCompressionOptions * nvttCreateCompressionOptions();
NVTT_API void nvttDestroyCompressionOptions(NvttCompressionOptions * compressionOptions);
@ -210,16 +210,14 @@ NVTT_API void nvttSetCompressionOptionsColorWeights(NvttCompressionOptions * com
NVTT_API void nvttSetCompressionOptionsPixelFormat(NvttCompressionOptions * compressionOptions, unsigned int bitcount, unsigned int rmask, unsigned int gmask, unsigned int bmask, unsigned int amask);
NVTT_API void nvttSetCompressionOptionsQuantization(NvttCompressionOptions * compressionOptions, NvttBoolean colorDithering, NvttBoolean alphaDithering, NvttBoolean binaryAlpha, int alphaThreshold);
// OutputOptions class.
NVTT_API NvttOutputOptions * nvttCreateOutputOptions();
NVTT_API void nvttDestroyOutputOptions(NvttOutputOptions * outputOptions);
NVTT_API void nvttSetOutputOptionsFileName(NvttOutputOptions * outputOptions, const char * fileName);
NVTT_API void nvttSetOutputOptionsOutputHeader(NvttOutputOptions * outputOptions, NvttBoolean b);
//NVTT_API void nvttSetOutputOptionsErrorHandler(NvttOutputOptions * outputOptions, nvttErrorHandler errorHandler);
//NVTT_API void nvttSetOutputOptionsOutputHandler(NvttOutputOptions * outputOptions, nvttOutputHandler outputHandler, nvttImageHandler imageHandler);
NVTT_API void nvttSetOutputOptionsErrorHandler(NvttOutputOptions * outputOptions, nvttErrorHandler errorHandler);
NVTT_API void nvttSetOutputOptionsOutputHandler(NvttOutputOptions * outputOptions, nvttOutputHandler outputHandler, nvttImageHandler imageHandler);
// Compressor class.
NVTT_API NvttCompressor * nvttCreateCompressor();
@ -228,6 +226,7 @@ NVTT_API void nvttDestroyCompressor(NvttCompressor * compressor);
NVTT_API NvttBoolean nvttCompress(const NvttCompressor * compressor, const NvttInputOptions * inputOptions, const NvttCompressionOptions * compressionOptions, const NvttOutputOptions * outputOptions);
NVTT_API int nvttEstimateSize(const NvttCompressor * compressor, const NvttInputOptions * inputOptions, const NvttCompressionOptions * compressionOptions);
NVTT_API void nvttEnableCudaCompression(NvttCompressor * compressor, NvttBoolean enable);
// Global functions.
NVTT_API const char * nvttErrorString(NvttError e);

Loading…
Cancel
Save