1 //-----------------------------------------------------------------------------
2 //
3 // ImageLib Sources
4 // Copyright (C) 2000-2009 by Denton Woods
5 // Last modified: 01/19/2009
6 //
7 // Filename: src-IL/src/il_nvidia.cpp
8 //
9 // Description: Implements access to the nVidia Texture Tools library.
10 //
11 //-----------------------------------------------------------------------------
12
13
14 #include "il_internal.h"
15 #include "il_dds.h"
16 #include "il_manip.h"
17 #include <limits.h>
18
19
20 #ifdef IL_USE_DXTC_NVIDIA
21 #include <nvtt/nvtt.h>
22
23 using namespace nvtt;
24
25 #if defined(_WIN32) && defined(IL_USE_PRAGMA_LIBS)
26 #if defined(_MSC_VER) || defined(__BORLANDC__)
27 #ifndef _DEBUG
28 #pragma comment(lib, "nvcore.lib")
29 #pragma comment(lib, "nvtt.lib")
30 #else
31 #pragma comment(lib, "nvcore-d.lib")
32 #pragma comment(lib, "nvtt-d.lib")
33 #endif
34 #endif
35 #endif
36
37
38 struct ilOutputHandlerMem : public nvtt::OutputHandler
39 {
ilOutputHandlerMemilOutputHandlerMem40 ilOutputHandlerMem(ILuint Width, ILuint Height, ILenum DxtType)
41 {
42 Width = Width + (4 - (Width % 4)) % 4; // Operates on 4x4 blocks,
43 Height = Height + (4 - (Height % 4)) % 4; // so gives extra room.
44
45 switch (DxtType)
46 {
47 case IL_DXT1:
48 case IL_DXT1A:
49 Size = Width * Height / 2;
50 break;
51 case IL_DXT3:
52 case IL_DXT5:
53 Size = Width * Height;
54 break;
55
56 default: // NVTT does not accept DXT2 or DXT4.
57 // Should error somehow...
58 break;
59 }
60 NewData = (ILubyte*)ialloc(Size);
61 if (NewData == NULL)
62 return;
63 Temp = NewData;
64 }
65
beginImageilOutputHandlerMem66 virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel)
67 {
68 // ignore.
69 }
writeDatailOutputHandlerMem70 virtual bool writeData(const void *data, int size)
71 {
72 memcpy(Temp, data, size);
73 Temp += size;
74 return true;
75 }
76
77 ILubyte *NewData, *Temp;
78 ILuint Size;
79 };
80
81
82 //! Compresses data to a DXT format using nVidia's Texture Tools library.
83 // The data must be in unsigned byte RGBA format. The alpha channel will be ignored if DxtType is IL_DXT1.
84 // DxtSize is used to return the size in bytes of the DXTC data returned.
ilNVidiaCompressDXT(ILubyte * Data,ILuint Width,ILuint Height,ILuint Depth,ILenum DxtFormat,ILuint * DxtSize)85 ILAPI ILubyte* ILAPIENTRY ilNVidiaCompressDXT(ILubyte *Data, ILuint Width, ILuint Height, ILuint Depth, ILenum DxtFormat, ILuint *DxtSize)
86 {
87 if (Data == NULL) { // We cannot operate on a null pointer.
88 ilSetError(IL_INVALID_PARAM);
89 return NULL;
90 }
91
92 // The nVidia Texture Tools library does not support volume textures yet.
93 if (Depth != 1) {
94 ilSetError(IL_INVALID_PARAM);
95 return NULL;
96 }
97
98 InputOptions inputOptions;
99 inputOptions.setTextureLayout(TextureType_2D, Width, Height);
100 inputOptions.setMipmapData(Data, Width, Height);
101 inputOptions.setMipmapGeneration(false, -1); //@TODO: Use this in certain cases.
102
103 OutputOptions outputOptions;
104 ilOutputHandlerMem outputHandler(Width, Height, DxtFormat);
105 outputOptions.setOutputHeader(false);
106 outputOptions.setOutputHandler(&outputHandler);
107
108 if (outputHandler.NewData == NULL)
109 return NULL;
110
111 CompressionOptions compressionOptions;
112 switch (DxtFormat)
113 {
114 case IL_DXT1:
115 compressionOptions.setFormat(Format_DXT1);
116 break;
117 case IL_DXT1A:
118 compressionOptions.setFormat(Format_DXT1a);
119 break;
120 case IL_DXT3:
121 compressionOptions.setFormat(Format_DXT1);
122 break;
123 case IL_DXT5:
124 compressionOptions.setFormat(Format_DXT5);
125 break;
126 default: // Does not support DXT2 or DXT4.
127 ilSetError(IL_INVALID_PARAM);
128 break;
129 }
130
131 Compressor compressor;
132 compressor.process(inputOptions, compressionOptions, outputOptions);
133
134 *DxtSize = outputHandler.Size;
135 return outputHandler.NewData;
136 }
137
138
139
140 //
141 //
142 // The following is just a repeat of above, but it works generically on file streams or lumps.
143 // @TODO: Merge these two together.
144 //
145 //
146
147
148 struct ilOutputHandlerFile : public nvtt::OutputHandler
149 {
ilOutputHandlerFileilOutputHandlerFile150 ilOutputHandlerFile(ILuint Width, ILuint Height, ILenum DxtType)
151 {
152 return;
153 }
154
beginImageilOutputHandlerFile155 virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel)
156 {
157 // ignore.
158 }
writeDatailOutputHandlerFile159 virtual bool writeData(const void *data, int size)
160 {
161 if (iwrite(data, 1, size) == size)
162 return true;
163 return false;
164 }
165
166 };
167
168
169 //! Compresses data to a DXT format using nVidia's Texture Tools library.
170 // This version is supposed to be completely internal to DevIL.
171 // The data must be in unsigned byte RGBA format. The alpha channel will be ignored if DxtType is IL_DXT1.
ilNVidiaCompressDXTFile(ILubyte * Data,ILuint Width,ILuint Height,ILuint Depth,ILenum DxtFormat)172 ILuint ilNVidiaCompressDXTFile(ILubyte *Data, ILuint Width, ILuint Height, ILuint Depth, ILenum DxtFormat)
173 {
174 ILuint FilePos = itellw();
175
176 // The nVidia Texture Tools library does not support volume textures yet.
177 if (Depth != 1) {
178 ilSetError(IL_INVALID_PARAM);
179 return 0;
180 }
181
182 InputOptions inputOptions;
183 inputOptions.setTextureLayout(TextureType_2D, Width, Height);
184 inputOptions.setMipmapData(Data, Width, Height);
185 inputOptions.setMipmapGeneration(false, -1); //@TODO: Use this in certain cases.
186
187 OutputOptions outputOptions;
188 ilOutputHandlerFile outputHandler(Width, Height, DxtFormat);
189 outputOptions.setOutputHeader(false);
190 outputOptions.setOutputHandler(&outputHandler);
191
192 CompressionOptions compressionOptions;
193 switch (DxtFormat)
194 {
195 case IL_DXT1:
196 compressionOptions.setFormat(Format_DXT1);
197 break;
198 case IL_DXT1A:
199 compressionOptions.setFormat(Format_DXT1a);
200 break;
201 case IL_DXT3:
202 compressionOptions.setFormat(Format_DXT1);
203 break;
204 case IL_DXT5:
205 compressionOptions.setFormat(Format_DXT5);
206 break;
207 default: // Does not support DXT2 or DXT4.
208 ilSetError(IL_INVALID_PARAM);
209 break;
210 }
211
212 Compressor compressor;
213 compressor.process(inputOptions, compressionOptions, outputOptions);
214
215 return itellw() - FilePos; // Return the number of characters written.
216 }
217
218 #else
219 // Let's have this so that the function is always created and exported, even if it does nothing.
ilNVidiaCompressDXT(ILubyte * Data,ILuint Width,ILuint Height,ILuint Depth,ILenum DxtFormat,ILuint * DxtSize)220 ILAPI ILubyte* ILAPIENTRY ilNVidiaCompressDXT(ILubyte *Data, ILuint Width, ILuint Height, ILuint Depth, ILenum DxtFormat, ILuint *DxtSize)
221 {
222 //@TODO: Do we need to set an error message?
223 return NULL;
224 }
225
226 #endif//IL_NO_DXTC_NVIDIA
227