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