1 // dxtctool.cpp: implementation of DXTC Tools functions.
2 //
3 // Copyright (C) 2002 Tanguy Fautr�.
4 // For conditions of distribution and use,
5 // see copyright notice in dxtctool.h
6 //
7 //////////////////////////////////////////////////////////////////////
8 
9 #include "dxtctool.h"
10 
11 
12 namespace dxtc_tool {
13 
14     const size_t dxtc_pixels::BSIZE_DXT1 = 8;
15     const size_t dxtc_pixels::BSIZE_DXT3 = 16;
16     const size_t dxtc_pixels::BSIZE_DXT5 = 16;
17     const size_t dxtc_pixels::BSIZE_ALPHA_DXT3 = 8;
18     const size_t dxtc_pixels::BSIZE_ALPHA_DXT5 = 8;
19 
20 
21 //////////////////////////////////////////////////////////////////////
22 // Construction/Destruction
23 //////////////////////////////////////////////////////////////////////
24 
25 
26 
27 //////////////////////////////////////////////////////////////////////
28 // Members Functions
29 //////////////////////////////////////////////////////////////////////
30 
OpenGLSize() const31 bool dxtc_pixels::OpenGLSize() const
32 {
33     size_t Width = m_Width;
34     size_t Height = m_Height;
35     // size_t TotalTrueBits = 0;
36 
37     if ((Width == 0) || (Height == 0))
38         return false;
39 
40     for (; (Width % 2) == 0; Width /= 2);
41     for (; (Height % 2) == 0; Height /= 2);
42 
43     if ((Width != 1) || (Height != 1))
44         return false;
45     else
46         return true;
47 }
48 
49 
50 
VFlip() const51 bool dxtc_pixels::VFlip() const
52 {
53     // Check that the given dimensions are 2^x, 2^y
54     if (! OpenGLSize())
55         return false;
56 
57     // Check that the given format are supported
58     if (! SupportedFormat())
59         return false;
60 
61     // Nothing to do if Height == 1
62     if (m_Height == 1)
63         return true;
64 
65     if (DXT1())
66         VFlip_DXT1();
67     else if (DXT3())
68         VFlip_DXT3();
69     else if (DXT5())
70         VFlip_DXT5();
71     else
72         return false; // We should never get there
73 
74     return true;
75 }
76 
77 
78 
VFlip_DXT1() const79 void dxtc_pixels::VFlip_DXT1() const
80 {
81     // const size_t Size = ((m_Width + 3) / 4) * ((m_Height + 3) / 4) * BSIZE_DXT1;
82     dxtc_int8 * pPixels = (dxtc_int8 * ) m_pPixels;
83 
84     if (m_Height == 2)
85         for (size_t j = 0; j < (m_Width + 3) / 4; ++j)
86             BVF_Color_H2(pPixels + j * BSIZE_DXT1);
87 
88     if (m_Height == 4)
89         for (size_t j = 0; j < (m_Width + 3) / 4; ++j)
90             BVF_Color_H4(pPixels + j * BSIZE_DXT1);
91 
92     if (m_Height > 4)
93         for (size_t i = 0; i < ((m_Height + 7) / 8); ++i)
94             for (size_t j = 0; j < (m_Width + 3) / 4; ++j) {
95                 const size_t TargetRow = ((m_Height + 3) / 4) - (i + 1);
96                 BVF_Color(GetBlock(i, j, BSIZE_DXT1), GetBlock(TargetRow, j, BSIZE_DXT1));
97             }
98 }
99 
100 
101 
VFlip_DXT3() const102 void dxtc_pixels::VFlip_DXT3() const
103 {
104     // const size_t Size = ((m_Width + 3) / 4) * ((m_Height + 3) / 4) * BSIZE_DXT3;
105     // dxtc_int8 * const pPixels = (dxtc_int8 * const) m_pPixels;
106 
107     if (m_Height == 2)
108         for (size_t j = 0; j < (m_Width + 3) / 4; ++j) {
109             BVF_Alpha_DXT3_H2(((dxtc_int8 * ) m_pPixels) + (j * BSIZE_DXT3));
110             BVF_Color_H2(((dxtc_int8 * ) m_pPixels) + (j * BSIZE_DXT3 + BSIZE_ALPHA_DXT3));
111         }
112 
113     if (m_Height == 4)
114         for (size_t j = 0; j < (m_Width + 3) / 4; ++j) {
115             BVF_Alpha_DXT3_H4(((dxtc_int8 * ) m_pPixels) + (j * BSIZE_DXT3));
116             BVF_Color_H4(((dxtc_int8 * ) m_pPixels) + (j * BSIZE_DXT3 + BSIZE_ALPHA_DXT3));
117         }
118 
119     if (m_Height > 4)
120         for (size_t i = 0; i < ((m_Height + 7) / 8); ++i)
121             for (size_t j = 0; j < (m_Width + 3) / 4; ++j) {
122                 const size_t TargetRow = ((m_Height + 3) / 4) - (i + 1);
123                 BVF_Alpha_DXT3(GetBlock(i, j, BSIZE_DXT3), GetBlock(TargetRow, j, BSIZE_DXT3));
124                 BVF_Color(((dxtc_int8 * ) GetBlock(i, j, BSIZE_DXT3)) + BSIZE_ALPHA_DXT3,
125                           ((dxtc_int8 * ) GetBlock(TargetRow, j, BSIZE_DXT3)) + BSIZE_ALPHA_DXT3);
126             }
127 }
128 
129 
130 
VFlip_DXT5() const131 void dxtc_pixels::VFlip_DXT5() const
132 {
133     // const size_t Size = ((m_Width + 3) / 4) * ((m_Height + 3) / 4) * BSIZE_DXT5;
134     // dxtc_int8 * const pPixels = (dxtc_int8 * const) m_pPixels;
135 
136     if (m_Height == 2)
137         for (size_t j = 0; j < (m_Width + 3) / 4; ++j) {
138             BVF_Alpha_DXT5_H2(((dxtc_int8 * ) m_pPixels) + (j * BSIZE_DXT5));
139             BVF_Color_H2(((dxtc_int8 * ) m_pPixels) + (j * BSIZE_DXT5 + BSIZE_ALPHA_DXT5));
140         }
141 
142     if (m_Height == 4)
143         for (size_t j = 0; j < (m_Width + 3) / 4; ++j) {
144             BVF_Alpha_DXT5_H4(((dxtc_int8 * ) m_pPixels) + (j * BSIZE_DXT5));
145             BVF_Color_H4(((dxtc_int8 * ) m_pPixels) + (j * BSIZE_DXT5 + BSIZE_ALPHA_DXT5));
146         }
147 
148     if (m_Height > 4)
149         for (size_t i = 0; i < ((m_Height + 7) / 8); ++i)
150             for (size_t j = 0; j < (m_Width + 3) / 4; ++j) {
151                 const size_t TargetRow = ((m_Height + 3) / 4) - (i + 1);
152                 BVF_Alpha_DXT5(GetBlock(i, j, BSIZE_DXT5), GetBlock(TargetRow, j, BSIZE_DXT5));
153                 BVF_Color(((dxtc_int8 * ) GetBlock(i, j, BSIZE_DXT5)) + BSIZE_ALPHA_DXT5,
154                           ((dxtc_int8 * ) GetBlock(TargetRow, j, BSIZE_DXT5)) + BSIZE_ALPHA_DXT5);
155             }
156 }
157 
158 //
159 // Structure of a DXT-1 compressed texture block
160 // see page "Opaque and 1-Bit Alpha Textures (Direct3D 9)" on http://msdn.microsoft.com
161 // url at time of writing http://msdn.microsoft.com/en-us/library/bb147243(v=VS.85).aspx
162 //
163 struct DXT1TexelsBlock
164 {
165     unsigned short color_0;     // colors at their
166     unsigned short color_1;     // extreme
167     unsigned int   texels4x4;   // interpolated colors (2 bits per texel)
168 };
169 struct DXT3TexelsBlock
170 {
171     unsigned short alpha4[4];   // alpha values (4 bits per texel) - 64 bits
172     unsigned short color_0;     // colors at their
173     unsigned short color_1;     // extreme
174     unsigned int   texels4x4;   // interpolated colors (2 bits per texel)
175 };
176 
177 struct DXT5TexelsBlock
178 {
179     unsigned char  alpha_0;     // alpha at their
180     unsigned char  alpha_1;     // extreme
181     unsigned char  alpha3[6];   // alpha index values (3 bits per texel)
182     unsigned short color_0;     // colors at their
183     unsigned short color_1;     // extreme
184     unsigned int   texels4x4;   // interpolated colors (2 bits per texel)
185 };
186 
isCompressedImageTranslucent(size_t width,size_t height,GLenum format,void * imageData)187 bool isCompressedImageTranslucent(size_t width, size_t height, GLenum format, void * imageData)
188 {
189     // OSG_NOTICE<<"isCompressedImageTranslucent("<<width<<", "<<height<<", "<<format<<", "<<imageData<<")"<<std::endl;
190     int blockCount = ((width + 3) >> 2) * ((height + 3) >> 2);
191     switch(format)
192     {
193         case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT):
194             return false;
195 
196         case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT):
197         {
198             const DXT1TexelsBlock *texelsBlock = reinterpret_cast<const DXT1TexelsBlock*>(imageData);
199 
200             // Only do the check on the first mipmap level, and stop when we
201             // see the first alpha texel
202             int i = blockCount;
203             while (i>0)
204             {
205                 // See if this block might contain transparent texels
206                 if (texelsBlock->color_0<=texelsBlock->color_1)
207                 {
208                     // Scan the texels block for the '11' bit pattern that
209                     // indicates a transparent texel
210                     int j = 0;
211                     while (j < 32)
212                     {
213                         // Check for the '11' bit pattern on this texel
214                         if ( ((texelsBlock->texels4x4 >> j) & 0x03) == 0x03)
215                         {
216                             // Texture is using the 1-bit alpha encoding, so we
217                             return true;
218                         }
219 
220                         // Next texel
221                         j += 2;
222                     }
223                 }
224 
225                 // Next block
226                 --i;
227                 ++texelsBlock;
228             }
229             return false;
230         }
231 
232         case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT):
233         {
234             const DXT3TexelsBlock *texelsBlock = reinterpret_cast<const DXT3TexelsBlock*>(imageData);
235             // Only do the check on the first mipmap level, and stop when we see the first alpha texel
236             int i = blockCount;
237             while (i>0)
238             {
239                 for (int j =0; j < 4; ++j)
240                     if ( texelsBlock->alpha4[j] != 0xFFFF) //4 pixels at once
241                             return true; //not fully opaque
242                 // Next block
243                 --i;
244                 ++texelsBlock;
245             }
246             return false;
247         }
248         case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT):
249         {
250             const DXT5TexelsBlock *texelsBlock = reinterpret_cast<const DXT5TexelsBlock*>(imageData);
251             // Only do the check on the first mipmap level, and stop when we see the first alpha texel
252             int i = blockCount;
253             unsigned char alphaBlock[8];
254             while (i>0)
255             {
256                 bool eightStep = texelsBlock->alpha_0 > texelsBlock->alpha_1;
257                 alphaBlock[0] = texelsBlock->alpha_0;
258                 alphaBlock[1] = texelsBlock->alpha_1;
259                 if (eightStep) {
260                     if (texelsBlock->alpha_0 < 255) return true; //not fully opaque
261                     alphaBlock[2] = (6 * alphaBlock[0] + 1 * alphaBlock[1] + 3) / 7;    // bit code 010
262                     alphaBlock[3] = (5 * alphaBlock[0] + 2 * alphaBlock[1] + 3) / 7;    // bit code 011
263                     alphaBlock[4] = (4 * alphaBlock[0] + 3 * alphaBlock[1] + 3) / 7;    // bit code 100
264                     alphaBlock[5] = (3 * alphaBlock[0] + 4 * alphaBlock[1] + 3) / 7;    // bit code 101
265                     alphaBlock[6] = (2 * alphaBlock[0] + 5 * alphaBlock[1] + 3) / 7;    // bit code 110
266                     alphaBlock[7] = (1 * alphaBlock[0] + 6 * alphaBlock[1] + 3) / 7;    // bit code 111
267                 } else {
268                     alphaBlock[2] = (4 * alphaBlock[0] + 1 * alphaBlock[1] + 2) / 5;    // bit code 010
269                     alphaBlock[3] = (3 * alphaBlock[0] + 2 * alphaBlock[1] + 2) / 5;    // bit code 011
270                     alphaBlock[4] = (2 * alphaBlock[0] + 3 * alphaBlock[1] + 2) / 5;    // bit code 100
271                     alphaBlock[5] = (1 * alphaBlock[0] + 4 * alphaBlock[1] + 2) / 5;    // bit code 101
272                     alphaBlock[6] = 0;    // bit code 110
273                     alphaBlock[7] = 255;    // bit code 111
274                 }
275 
276                 int last_added_byte = 1;
277                 unsigned short running_a_index = texelsBlock->alpha3[0] + (((unsigned short)texelsBlock->alpha3[last_added_byte]) << 8);
278                 for (int j = 0; j < 16; ++j) {
279                     unsigned char alphaIndex = running_a_index & 0x7;
280                     if (alphaBlock[alphaIndex] < 255) return true; //not fully opaque
281                     running_a_index >>= 3;
282                     if ((3 * j / 8) == last_added_byte) {
283                         ++last_added_byte;
284                         //(&texelsBlock->alpha3[0]) to avoid gcc warning: array subscript is above array bounds [-Warray-bounds]
285                         running_a_index += (((unsigned short)(&(texelsBlock->alpha3[0]))[last_added_byte]) << (8 - (3 * j & 0x7)));
286                     }
287                 }
288                 // Next block
289                 --i;
290                 ++texelsBlock;
291             }
292             return false;
293         }
294         default:
295             break;
296     }
297 
298     return false;
299 }
300 
interpolateColors21(unsigned short color1,unsigned short color2)301 unsigned short interpolateColors21(unsigned short color1, unsigned short color2) {
302     unsigned short result = (((color1 >> 11) * 2 + (color2 >> 11)  + 1) / 3) << 11;
303     result += (((color1 >> 5 & 0x3F) * 2 + (color2 >> 5 & 0x3F)  + 1) / 3) << 5;
304     result += (((color1 & 0x1F) * 2 + (color2 & 0x1F)  + 1) / 3);
305     return result;
306 }
interpolateColors11(unsigned short color1,unsigned short color2)307 unsigned short interpolateColors11(unsigned short color1, unsigned short color2) {
308     unsigned short result = (((color1 >> 11)  + (color2 >> 11) ) / 2) << 11;
309     result += (((color1 >> 5 & 0x3F)  + (color2 >> 5 & 0x3F)) / 2) << 5;
310     result += (((color1 & 0x1F)  + (color2 & 0x1F) ) / 2);
311     return result;
312 }
313 
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)314 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)
315 {
316     unsigned short color16 = 0;//RGB 5:6:5 format
317 
318 
319     unsigned int slab4Count = (depth & ~0x3); //4*floor(d/4)
320     unsigned int col = (s >> 2);//(floor(x/4)
321     unsigned int row = (t >> 2);//(floor(y/4)
322     unsigned int blockWidth = (width + 3) >> 2;//ceil(w/4)
323     unsigned int blockHeight = (height + 3) >> 2;//ceil(h/4)
324     int blockNumber = col + blockWidth * row ; // block to jump to
325 
326     if (depth > 1) {
327 // https://www.opengl.org/registry/specs/NV/texture_compression_vtc.txt
328 //    if (z >= 4*floor(d/4)) {
329 //        blockIndex = blocksize * (ceil(w/4) * ceil(h/4) * 4*floor(d/4) + floor(x/4) + ceil(w/4) * (floor(y/4) + ceil(h/4) * (z-4*floor(d/4)) ));
330 //    } else {
331 //        blockIndex = blocksize * 4 * (floor(x/4) + ceil(w/4) * (floor(y/4) + ceil(h/4) * floor(z/4)));
332 //    }
333 // note floor(a/4) = (a >> 2)
334 // note 4*floor(a/4) = a & ~0x3
335 // note ceil(a/4) = ((a + 3) >> 2)
336 //
337 //  rewrite: this describes the final blocks as consecutive 4x4x1 blocks - and thats not in the wording of the specs
338 //    if (r >= slab4Count) {
339 //        blockNumber = (blockWidth * blockHeight * slab4Count  + col + blockWidth * (row + blockHeight * (r-slab4Count) ));
340 //    } else {
341 //      blockNumber = 4 * (col + blockWidth * (row + blockHeight * (r >> 2)) );
342 //    }
343 
344 // or in the version of the openGL specs:
345 //    if (z >= 4*floor(d/4)) {
346 //        blockIndex = blocksize * (ceil(w/4) * ceil(h/4) * 4*floor(d/4) + (z - 4*floor(d/4)) * ( (floor(x/4) + ceil(w/4) * (floor(y/4) );
347 //    } else {
348 //        blockIndex = blocksize * 4 * (floor(x/4) + ceil(w/4) * (floor(y/4) + ceil(h/4) * floor(z/4)));
349 //    }
350 
351     unsigned int sub_r = r & 0x3;//(r-slab4Count)
352     if (r >= slab4Count) { //slice number beyond  4x4x4 slabs
353         unsigned int blockDepth = depth & 0x3;// equals: depth - slab4Count;//depth of this final block: 1/2/3 in case of 4x4x1; 4x4x2 or 4x4x3 bricks
354         blockNumber = (blockWidth * blockHeight * slab4Count //jump full 4x4x4 slabs
355         + blockDepth * ( col + blockWidth * row )
356         + sub_r);
357     } else {
358         blockNumber = 4 * (col + blockWidth * (row + blockHeight * (r >> 2)) ) + sub_r;
359     }
360     }
361 
362     int sub_s = s & 0x3;
363     int sub_t = t & 0x3;
364     switch (format)
365     {
366     case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT) :
367     case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) :
368     {
369         const DXT1TexelsBlock *texelsBlock = reinterpret_cast<const DXT1TexelsBlock*>(imageData);
370         texelsBlock += blockNumber; //jump to block
371         char index = (texelsBlock->texels4x4 >> (2 * sub_s + 8 * sub_t)) & 0x3; //two bit "index value"
372         color[3] = 255;
373         switch (index) {
374         case 0:
375             color16 = texelsBlock->color_0;
376             break;
377         case 1:
378             color16 = texelsBlock->color_1;
379             break;
380         case 2:
381             if (texelsBlock->color_0 > texelsBlock->color_1) {
382                 color16 = interpolateColors21(texelsBlock->color_0, texelsBlock->color_1);
383             }
384             else {
385                 color16 = interpolateColors11(texelsBlock->color_0, texelsBlock->color_1);
386             }
387             break;
388         case 3:
389             if (texelsBlock->color_0 > texelsBlock->color_1) {
390                 color16 = interpolateColors21(texelsBlock->color_1, texelsBlock->color_0);
391             }
392             else {
393                 color16 = 0;//black
394                 if (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) color[3] = 0;//transparent
395             }
396             break;
397         }
398         break;
399     }
400     case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) :
401     {
402         const DXT3TexelsBlock *texelsBlock = reinterpret_cast<const DXT3TexelsBlock*>(imageData);
403         texelsBlock += blockNumber; //jump to block
404         color[3] = 17 * (texelsBlock->alpha4[sub_t] >> 4 * sub_s & 0xF);
405         char index = (texelsBlock->texels4x4 >> (2 * sub_s + 8 * sub_t)) & 0x3; //two bit "index value"
406         switch (index) {
407         case 0:
408             color16 = texelsBlock->color_0;
409             break;
410         case 1:
411             color16 = texelsBlock->color_1;
412             break;
413         case 2:
414             color16 = interpolateColors21(texelsBlock->color_0, texelsBlock->color_1);
415             break;
416         case 3:
417             color16 = interpolateColors21(texelsBlock->color_1, texelsBlock->color_0);
418             break;
419         }
420         break;
421     }
422     case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) :
423     {
424         const DXT5TexelsBlock *texelsBlock = reinterpret_cast<const DXT5TexelsBlock*>(imageData);
425         texelsBlock += blockNumber; //jump to block
426         char index = (texelsBlock->texels4x4 >> (2 * sub_s + 8 * sub_t)) & 0x3; //two bit "index value"
427         switch (index) {
428         case 0:
429             color16 = texelsBlock->color_0;
430             break;
431         case 1:
432             color16 = texelsBlock->color_1;
433             break;
434         case 2:
435             color16 = interpolateColors21(texelsBlock->color_0, texelsBlock->color_1);
436             break;
437         case 3:
438             color16 = interpolateColors21(texelsBlock->color_1, texelsBlock->color_0);
439             break;
440         }
441         char pixel = sub_s + 4 * sub_t;//pixel number in block: 0 - 15
442         char firstBit = 3 * pixel;//least significant bit: range 0 - 45
443         unsigned char alpha_index;
444         if ((firstBit & 0x7) < 6) {
445             alpha_index = texelsBlock->alpha3[firstBit >> 3] >> (firstBit & 0x7) & 0x7;//grab byte containing least significant bit; shift and get 3 bits
446         } else {
447             alpha_index = texelsBlock->alpha3[firstBit >> 3] >> (firstBit & 0x7);
448             alpha_index |= texelsBlock->alpha3[1 + (firstBit >> 3)] << (8 - (firstBit & 0x7));
449             alpha_index &= 0x7;
450         }
451         if (alpha_index == 0) {
452             color[3] = texelsBlock->alpha_0;
453         } else {
454             if (alpha_index == 1) {
455                 color[3] = texelsBlock->alpha_1;
456             } else {
457                 if (texelsBlock->alpha_0 > texelsBlock->alpha_1) {
458                     color[3] = ((unsigned short)texelsBlock->alpha_0  * (8 - alpha_index) + (unsigned short)texelsBlock->alpha_1 * (alpha_index - 1) + 3) / 7;
459                 } else {
460                     if (alpha_index < 6) {
461                         color[3] = ((unsigned short)texelsBlock->alpha_0  * (6 - alpha_index) + (unsigned short)texelsBlock->alpha_1 * (alpha_index - 1) + 3) / 5;
462                     } else {
463                         if (alpha_index == 6) {
464                             color[3] = 0;
465                         } else {
466                             color[3] = 255;
467                         }
468                     }
469                 }
470             }
471         }
472         break;
473     }
474     default:
475         return false;
476     }
477     unsigned short colorChannel = color16 >> 11;//red - 5 bits
478     color[0] = colorChannel << 3 | colorChannel >> 2 ;
479     colorChannel = color16 >> 5 & 0x3F;//green - 6 bits
480     color[1] = colorChannel << 2 | colorChannel >> 3;
481     colorChannel = color16 & 0x1F;//blue - 5 bits
482     color[2] = colorChannel << 3 | colorChannel >> 2;
483     return true;
484 }
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)485 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)
486 {
487     unsigned int src_texels4x4;
488     unsigned int *dst_texels4x4 = NULL;
489     switch (format)
490     {
491     case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT) :
492     case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) :
493     {
494         const DXT1TexelsBlock *src_texelsBlock = reinterpret_cast<const DXT1TexelsBlock*>(src_block);
495         //make a copy as source might be equal to destination
496         src_texels4x4 = src_texelsBlock->texels4x4;   // interpolated colors (2 bits per texel)
497         DXT1TexelsBlock *dst_texelsBlock = reinterpret_cast<DXT1TexelsBlock*>(dst_block);
498         dst_texels4x4 = &dst_texelsBlock->texels4x4;
499 
500         break;
501     }
502     case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) :
503     {
504         const DXT3TexelsBlock *src_texelsBlock = reinterpret_cast<const DXT3TexelsBlock*>(src_block);
505         //make a copy as source might be equal to destination
506         src_texels4x4 = src_texelsBlock->texels4x4;   // interpolated colors (2 bits per texel)
507         DXT3TexelsBlock *dst_texelsBlock = reinterpret_cast<DXT3TexelsBlock*>(dst_block);
508         dst_texels4x4 = &dst_texelsBlock->texels4x4;
509         unsigned short src_alpha4[4];   // alpha values (4 bits per texel) - 64 bits
510 
511         memcpy(src_alpha4, src_texelsBlock->alpha4, 4 * sizeof(unsigned short));//make a copy as source might be equal to destination
512 
513         memset(dst_texelsBlock->alpha4, 0, 4 * sizeof(unsigned short)); //clear
514         osg::Vec3i source_pixel(srcOrigin);
515         for (int r = 0; r<4; r++)//rows
516         {
517             for (int c = 0; c<4; c++)//columns
518             {
519                 int sub_s = source_pixel.x() & 0x3;
520                 int sub_t = source_pixel.y() & 0x3;
521                 int shiftBits = 4 * sub_s;
522                 unsigned int alpha_value = src_alpha4[sub_t] >> shiftBits & 0xf; //four bit alpha values
523 
524                 shiftBits = 4 * c;//destination
525                 alpha_value <<= shiftBits;
526                 dst_texelsBlock->alpha4[r] |= alpha_value;
527 
528                 source_pixel = source_pixel + rowDelta;
529             }
530             source_pixel = source_pixel + columnDelta;
531         }
532         break;
533     }
534     case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) :
535     {
536         const DXT5TexelsBlock *src_texelsBlock = reinterpret_cast<const DXT5TexelsBlock*>(src_block);
537         //make a copy as source might be equal to destination
538         src_texels4x4 = src_texelsBlock->texels4x4;   // interpolated colors (2 bits per texel)
539         DXT5TexelsBlock *dst_texelsBlock = reinterpret_cast<DXT5TexelsBlock*>(dst_block);
540         dst_texels4x4 = &dst_texelsBlock->texels4x4;
541 
542         unsigned char  src_alpha3[6];   // alpha index values (3 bits per texel)
543 
544         memcpy(src_alpha3, src_texelsBlock->alpha3, 6 * sizeof(unsigned char));//make a copy as source might be equal to destination
545 
546         memset(dst_texelsBlock->alpha3, 0, 6 * sizeof(unsigned char)); //clear
547         osg::Vec3i source_pixel(srcOrigin);
548         unsigned int last_added_byte = 1;
549         unsigned short running_a_index = src_texelsBlock->alpha3[0] + (((unsigned short)src_texelsBlock->alpha3[last_added_byte]) << 8);
550         unsigned int j = 0;
551         for (int r = 0; r<4; r++)//rows
552         {
553             for (int c = 0; c<4; c++)//columns
554             {
555                 int sub_s = source_pixel.x() & 0x3;
556                 int sub_t = source_pixel.y() & 0x3;
557 
558                 unsigned char alphaIndex = running_a_index & 0x7;
559                 //store alphaIndex in output position:
560                 int shiftBits = 3 * sub_s + 12 * sub_t;//LSB
561                 dst_texelsBlock->alpha3[shiftBits >> 3] |= alphaIndex << (shiftBits & 0x7);
562                 if ((shiftBits & 0x7) > 5) {
563                     dst_texelsBlock->alpha3[1 + (shiftBits >> 3)] |= alphaIndex >> (8 - (shiftBits & 0x7));
564                 }
565 
566                 running_a_index >>= 3;
567                 if ((3 * ++j / 8) == last_added_byte) {
568                     ++last_added_byte;
569                     //(&texelsBlock->alpha3[0]) to avoid gcc warning: array subscript is above array bounds [-Warray-bounds]
570                     running_a_index += (((unsigned short)(&(src_texelsBlock->alpha3[0]))[last_added_byte]) << (8 - (3 * j & 0x7)));
571                 }
572                 source_pixel = source_pixel + rowDelta;
573             }
574             source_pixel = source_pixel + columnDelta;
575         }
576         break;
577     }
578     default:
579         return;
580     }//switch
581 
582     //all formats: rearrange the colors
583     *dst_texels4x4 = 0;//clear
584     osg::Vec3i source_pixel(srcOrigin);
585     for (int r = 0; r<4; r++)//rows
586     {
587         for (int c = 0; c<4; c++)//columns
588         {
589             int sub_s = source_pixel.x() & 0x3;
590             int sub_t = source_pixel.y() & 0x3;
591             int shiftBits = 2 * sub_s + 8 * sub_t;
592             unsigned int index = (src_texels4x4 >> (shiftBits)) & 0x3; //two bit "index value"
593 
594             shiftBits = 2 * c + 8 * r;//destination
595             index <<= shiftBits;
596             *dst_texels4x4 |= index;
597 
598             source_pixel = source_pixel + rowDelta;
599         }
600         source_pixel = source_pixel + columnDelta;
601     }
602 }
603 
compressedBlockStripAlhpa(const GLenum format,const unsigned char * src_block,unsigned char * dst_block)604 void compressedBlockStripAlhpa(const GLenum format, const unsigned char *src_block, unsigned char *dst_block) {
605     unsigned int src_texels4x4;
606     char reshuffle[4] = { 1, 0, 3, 2 };
607     switch (format)
608     {
609     default:
610     case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT) :
611     case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) :
612     {
613         const DXT1TexelsBlock *src_texelsBlock = reinterpret_cast<const DXT1TexelsBlock*>(src_block);
614         //make a copy as source might be equal to destination
615         src_texels4x4 = src_texelsBlock->texels4x4;   // interpolated colors (2 bits per texel)
616         DXT1TexelsBlock *dst_texelsBlock = reinterpret_cast<DXT1TexelsBlock*>(dst_block);
617         if (src_texelsBlock->color_0 > src_texelsBlock->color_1) {
618             // Four-color block
619             memcpy(dst_texelsBlock, src_texelsBlock, sizeof(DXT1TexelsBlock));
620         } else {
621             dst_texelsBlock->color_0 = src_texelsBlock->color_1;
622             dst_texelsBlock->color_1 = src_texelsBlock->color_0;
623             dst_texelsBlock->texels4x4 = 0;
624             for (unsigned int shiftBits = 0; shiftBits < 32; shiftBits += 2) {
625                 unsigned char index = src_texels4x4 >> shiftBits & 0x3; //two bit "index value"
626                 dst_texelsBlock->texels4x4 |= reshuffle[index] << shiftBits;
627             }
628 
629         }
630         break;
631     }
632     case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) :
633     case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) :
634     {
635         const DXT3TexelsBlock *src_texelsBlock = reinterpret_cast<const DXT3TexelsBlock*>(src_block);
636         //make a copy as source might be equal to destination
637         src_texels4x4 = src_texelsBlock->texels4x4;   // interpolated colors (2 bits per texel)
638         DXT1TexelsBlock *dst_texelsBlock = reinterpret_cast<DXT1TexelsBlock*>(dst_block);
639         if (src_texelsBlock->color_0 > src_texelsBlock->color_1) {
640             // Four-color block
641             memcpy(dst_texelsBlock, src_texelsBlock, sizeof(DXT3TexelsBlock));
642         }
643         else {
644             dst_texelsBlock->color_0 = src_texelsBlock->color_1;
645             dst_texelsBlock->color_1 = src_texelsBlock->color_0;
646             dst_texelsBlock->texels4x4 = 0;
647             for (unsigned int shiftBits = 0; shiftBits < 32; shiftBits += 2) {
648                 unsigned char index = src_texels4x4 >> shiftBits & 0x3; //two bit "index value"
649                 dst_texelsBlock->texels4x4 |= reshuffle[index] << shiftBits;
650 
651             }
652 
653         }
654         break;
655     }
656     }
657 }
658 } // namespace dxtc_tool
659