1 // dxtctool.h: interface for the DXTC tools.
2 //
3 //////////////////////////////////////////////////////////////////////
4 //
5 //  Copyright (C) 2002 Tanguy Fautr.
6 //
7 //  This software is provided 'as-is', without any express or implied
8 //  warranty.  In no event will the authors be held liable for any damages
9 //  arising from the use of this software.
10 //
11 //  Permission is granted to anyone to use this software for any purpose,
12 //  including commercial applications, and to alter it and redistribute it
13 //  freely, subject to the following restrictions:
14 //
15 //  1. The origin of this software must not be misrepresented; you must not
16 //     claim that you wrote the original software. If you use this software
17 //     in a product, an acknowledgment in the product documentation would be
18 //     appreciated but is not required.
19 //  2. Altered source versions must be plainly marked as such, and must not be
20 //     misrepresented as being the original software.
21 //  3. This notice may not be removed or altered from any source distribution.
22 //
23 //  Tanguy Fautr
24 //  softdev@telenet.be
25 //
26 //////////////////////////////////////////////////////////////////////
27 //
28 //                        DXTC Tools: Vertical Flip.
29 //                        *************************
30 //
31 // Current version: 1.00 BETA 1 (27/08/2002)
32 //
33 // Comment: Only works with DXTC mode supported by OpenGL.
34 //          (currently: DXT1/DXT3/DXT5)
35 //
36 // History: -
37 //
38 //////////////////////////////////////////////////////////////////////
39 
40 #ifndef DXTCTOOL_H
41 #define DXTCTOOL_H
42 
43 #include <osg/GL>
44 #include <osg/Texture>
45 #include <osg/Vec3i>
46 
47 #if defined(_MSC_VER)
48 
49     typedef __int8  dxtc_int8;
50     typedef __int16 dxtc_int16;
51     typedef __int32 dxtc_int32;
52     typedef __int64 dxtc_int64;
53 
54     #define HEX_0x000000000000FFFF 0x000000000000FFFF
55     #define HEX_0x000000000FFF0000 0x000000000FFF0000
56     #define HEX_0x000000FFF0000000 0x000000FFF0000000
57     #define HEX_0x000FFF0000000000 0x000FFF0000000000
58     #define HEX_0xFFF0000000000000 0xFFF0000000000000
59 
60 #else
61 
62     typedef char        dxtc_int8;
63     typedef short       dxtc_int16;
64     typedef int         dxtc_int32;
65     typedef long long   dxtc_int64;
66 
67     #define HEX_0x000000000000FFFF 0x000000000000FFFFll
68     #define HEX_0x000000000FFF0000 0x000000000FFF0000ll
69     #define HEX_0x000000FFF0000000 0x000000FFF0000000ll
70     #define HEX_0x000FFF0000000000 0x000FFF0000000000ll
71     #define HEX_0xFFF0000000000000 0xFFF0000000000000ll
72 
73 #endif
74 
75 namespace dxtc_tool {
76 
77 // C-like function wrappers
78 bool isDXTC(GLenum pixelFormat);
79 
80 bool VerticalFlip(size_t Width, size_t Height, GLenum Format, void * pPixels);
81 
82 bool isCompressedImageTranslucent(size_t Width, size_t Height, GLenum Format, void * pPixels);
83 
84 //interpolate RGB565 colors with 2/3 part color1 and 1/3 part color2
85 unsigned short interpolateColors21(unsigned short color1, unsigned short color2);
86 //interpolate RGB565 colors with equal weights
87 unsigned short interpolateColors11(unsigned short color1, unsigned short color2);
88 
89 bool CompressedImageGetColor(unsigned char color[4], unsigned int s, unsigned int t, unsigned int r, int width, int height, int depth, GLenum format, unsigned char *imageData);
90 
91 void compressedBlockOrientationConversion(const GLenum format, const unsigned char *src_block, unsigned char *dst_block, const osg::Vec3i& srcOrigin, const osg::Vec3i& rowDelta, const osg::Vec3i& columnDelta);
92 
93 void compressedBlockStripAlhpa(const GLenum format, const unsigned char *src_block, unsigned char *dst_block);
94 // Class holding reference to DXTC image pixels
95 class dxtc_pixels
96 {
97 public:
98     inline dxtc_pixels(size_t Width, size_t Height, GLenum Format, void * pPixels);
99 
100     // Vertically flip the whole picture
101     bool VFlip() const;
102 
103 protected:
104 
105     dxtc_pixels& operator = (const dxtc_pixels&) { return *this; }
106 
107     // Limitation check functions
108     inline bool DXT1() const;
109     inline bool DXT3() const;
110     inline bool DXT5() const;
111     inline bool OpenGLSize() const;
112     inline bool SupportedFormat() const;
113 
114     // Vertical flipping functions
115     void VFlip_DXT1() const;
116     void VFlip_DXT3() const;
117     void VFlip_DXT5() const;
118 
119     // Block vertical flipping functions
120     inline void BVF_Color_H2(void * const pBlock) const;                            // V. flip one color block with its virtual height == 2
121     inline void BVF_Color_H4(void * const pBlock) const;                            // V. flip one color block with its virtual height == 4
122     inline void BVF_Color(void * const pBlock1, void * const pBlock2) const;        // V. flip and swap two color blocks, with their virtual height == 4
123     inline void BVF_Alpha_DXT3_H2(void * const pBlock) const;                        // V. flip one alpha (DXT3) block with its virtual height == 2
124     inline void BVF_Alpha_DXT3_H4(void * const pBlock) const;                        // V. flip one alpha (DXT3) block with its virtual height == 4
125     inline void BVF_Alpha_DXT3(void * const pBlock1, void * const pBlock2) const;    // V. flip and swap two alpha (DXT3) blocks, with their virtual height == 4
126     inline void BVF_Alpha_DXT5_H2(void * const pBlock) const;                        // V. flip one alpha (DXT5) block with its virtual height == 2
127     inline void BVF_Alpha_DXT5_H4(void * const pBlock) const;                        // V. flip one alpha (DXT5) block with its virtual height == 4
128     inline void BVF_Alpha_DXT5(void * const pBlock1, void * const pBlock2) const;    // V. flip and swap two alpha (DXT5) blocks, with their virtual height == 4
129 
130     // Block localization functions
131     inline void * GetBlock(size_t i, size_t j, size_t BlockSize) const;
132 
133     // mighty const and var
134     static const size_t BSIZE_DXT1;
135     static const size_t BSIZE_DXT3;
136     static const size_t BSIZE_DXT5;
137     static const size_t BSIZE_ALPHA_DXT3;
138     static const size_t BSIZE_ALPHA_DXT5;
139 
140     const size_t    m_Width;
141     const size_t    m_Height;
142     const GLenum    m_Format;
143     void * const    m_pPixels;
144 };
145 
146 
147 
148 
149 //////////////////////////////////////////////////////////////////////
150 // C-Like Function Wrappers
151 //////////////////////////////////////////////////////////////////////
152 
isDXTC(GLenum pixelFormat)153 inline bool isDXTC(GLenum pixelFormat)
154 {
155     switch(pixelFormat)
156     {
157         case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT):
158         case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT):
159         case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT):
160         case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT):
161             return true;
162         default:
163             return false;
164     }
165 }
166 
VerticalFlip(size_t Width,size_t Height,GLenum Format,void * pPixels)167 inline bool VerticalFlip(size_t Width, size_t Height, GLenum Format, void * pPixels) {
168     return (dxtc_pixels(Width, Height, Format, pPixels)).VFlip();
169 }
170 
171 
172 
173 //////////////////////////////////////////////////////////////////////
174 // dxtc_pixels Inline Functions
175 //////////////////////////////////////////////////////////////////////
176 
dxtc_pixels(size_t Width,size_t Height,GLenum Format,void * pPixels)177 inline dxtc_pixels::dxtc_pixels(size_t Width, size_t Height, GLenum Format, void * pPixels) :
178     m_Width(Width), m_Height(Height), m_Format(Format), m_pPixels(pPixels) { }
179 
180 
DXT1()181 inline bool dxtc_pixels::DXT1() const {
182     return ((m_Format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) || (m_Format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT));
183 }
184 
185 
DXT3()186 inline bool dxtc_pixels::DXT3() const {
187     return (m_Format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
188 }
189 
190 
DXT5()191 inline bool dxtc_pixels::DXT5() const {
192     return (m_Format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT);
193 }
194 
195 
SupportedFormat()196 inline bool dxtc_pixels::SupportedFormat() const {
197     return (DXT1() || DXT3() || DXT5());
198 }
199 
200 
BVF_Color_H2(void * const pBlock)201 inline void dxtc_pixels::BVF_Color_H2(void * const pBlock) const {
202     // Swap the two first row of pixels
203     dxtc_int8 * pP = ((dxtc_int8 *) pBlock) + 4;
204 
205     std::swap(pP[0], pP[1]);
206 }
207 
208 
BVF_Color_H4(void * const pBlock)209 inline void dxtc_pixels::BVF_Color_H4(void * const pBlock) const {
210     // Swap the first row of pixels with the last one, then the 2 middle row of pixels
211     dxtc_int8 * pP = ((dxtc_int8 *) pBlock) + 4;
212 
213     std::swap(pP[0], pP[3]);
214     std::swap(pP[1], pP[2]);
215 }
216 
217 
BVF_Color(void * const pBlock1,void * const pBlock2)218 inline void dxtc_pixels::BVF_Color(void * const pBlock1, void * const pBlock2) const {
219     // Swap the "2 colors" header (32bits each header)
220     dxtc_int32 * pHdr1 = (dxtc_int32 * ) pBlock1;
221     dxtc_int32 * pHdr2 = (dxtc_int32 * ) pBlock2;
222 
223     std::swap(* pHdr1, * pHdr2);
224 
225     // Now swap the pixel values
226     dxtc_int8 * pP1 = ((dxtc_int8 * ) pBlock1) + 4;
227     dxtc_int8 * pP2 = ((dxtc_int8 * ) pBlock2) + 4;
228 
229     std::swap(pP1[0], pP2[3]);
230     std::swap(pP1[1], pP2[2]);
231     std::swap(pP1[2], pP2[1]);
232     std::swap(pP1[3], pP2[0]);
233 }
234 
235 
BVF_Alpha_DXT3_H2(void * const pBlock)236 inline void dxtc_pixels::BVF_Alpha_DXT3_H2(void * const pBlock) const {
237     // Swap the two first row of pixels
238     dxtc_int16 * pP = (dxtc_int16 * ) pBlock;
239 
240     std::swap(pP[0], pP[1]);
241 }
242 
243 
BVF_Alpha_DXT3_H4(void * const pBlock)244 inline void dxtc_pixels::BVF_Alpha_DXT3_H4(void * const pBlock) const {
245     // Swap the first row of pixels with the last one, then the 2 middle row of pixels
246     dxtc_int16 * pP = (dxtc_int16 * ) pBlock;
247 
248     std::swap(pP[0], pP[3]);
249     std::swap(pP[1], pP[2]);
250 }
251 
252 
BVF_Alpha_DXT3(void * const pBlock1,void * const pBlock2)253 inline void dxtc_pixels::BVF_Alpha_DXT3(void * const pBlock1, void * const pBlock2) const {
254     // Swap all the pixel values
255     dxtc_int16 * pP1 = (dxtc_int16 * ) pBlock1;
256     dxtc_int16 * pP2 = (dxtc_int16 * ) pBlock2;
257 
258     std::swap(pP1[0], pP2[3]);
259     std::swap(pP1[1], pP2[2]);
260     std::swap(pP1[2], pP2[1]);
261     std::swap(pP1[3], pP2[0]);
262 }
263 
264 
BVF_Alpha_DXT5_H2(void * const pBlock)265 inline void dxtc_pixels::BVF_Alpha_DXT5_H2(void * const pBlock) const {
266     // Swap the two first row of pixels (kinda tricky with DXT5 unaligned encoding)
267     dxtc_int32 * pP = (dxtc_int32 * ) (((dxtc_int8 * ) pBlock) + 2);
268 
269     dxtc_int32 TmpDWord = (pP[0] & 0xFF000000);
270     TmpDWord |=    (pP[0] & 0x00000FFF) << 12;
271     TmpDWord |= (pP[0] & 0x00FFF000) >> 12;
272     pP[0] = TmpDWord;
273 }
274 
275 
276 
277 
278 
279 
BVF_Alpha_DXT5_H4(void * const pBlock)280 inline void dxtc_pixels::BVF_Alpha_DXT5_H4(void * const pBlock) const {
281     // Swap the first row of pixels with the last one, then the 2 middle row of pixels (tricky again)
282     dxtc_int64 * pB = (dxtc_int64 * ) pBlock;
283 
284     dxtc_int64 TmpQWord = (pB[0] & HEX_0x000000000000FFFF);
285     TmpQWord |= (pB[0] & HEX_0x000000000FFF0000) << 36;
286     TmpQWord |= (pB[0] & HEX_0x000000FFF0000000) << 12;
287     TmpQWord |= (pB[0] & HEX_0x000FFF0000000000) >> 12;
288     TmpQWord |= (pB[0] & HEX_0xFFF0000000000000) >> 36;
289     pB[0] = TmpQWord;
290 }
291 
292 
BVF_Alpha_DXT5(void * const pBlock1,void * const pBlock2)293 inline void dxtc_pixels::BVF_Alpha_DXT5(void * const pBlock1, void * const pBlock2) const {
294     // Swap all the pixel values (same trick for DXT5)
295     dxtc_int64 * pB1 = (dxtc_int64 * ) pBlock1;
296     dxtc_int64 * pB2 = (dxtc_int64 * ) pBlock2;
297 
298     dxtc_int64 TmpQWord1 = (pB1[0] & HEX_0x000000000000FFFF);
299     TmpQWord1 |= (pB1[0] & HEX_0x000000000FFF0000) << 36;
300     TmpQWord1 |= (pB1[0] & HEX_0x000000FFF0000000) << 12;
301     TmpQWord1 |= (pB1[0] & HEX_0x000FFF0000000000) >> 12;
302     TmpQWord1 |= (pB1[0] & HEX_0xFFF0000000000000) >> 36;
303 
304     dxtc_int64 TmpQWord2 = (pB2[0] & HEX_0x000000000000FFFF);
305     TmpQWord2 |= (pB2[0] & HEX_0x000000000FFF0000) << 36;
306     TmpQWord2 |= (pB2[0] & HEX_0x000000FFF0000000) << 12;
307     TmpQWord2 |= (pB2[0] & HEX_0x000FFF0000000000) >> 12;
308     TmpQWord2 |= (pB2[0] & HEX_0xFFF0000000000000) >> 36;
309 
310     pB1[0] = TmpQWord2;
311     pB2[0] = TmpQWord1;
312 }
313 
314 
GetBlock(size_t i,size_t j,size_t BlockSize)315 inline void * dxtc_pixels::GetBlock(size_t i, size_t j, size_t BlockSize) const {
316     const dxtc_int8 * pPixels = (const dxtc_int8 *) m_pPixels;
317 
318     return (void *) (pPixels + i * ((m_Width + 3) / 4) * BlockSize + j * BlockSize);
319 }
320 
321 
322 
323 
324 } // namespace dxtc_tool
325 
326 #endif // DXTCTOOL_H
327