diff --git a/src/osg/Image.cpp b/src/osg/Image.cpp index 1149acdc4..ed8175e46 100644 --- a/src/osg/Image.cpp +++ b/src/osg/Image.cpp @@ -1719,7 +1719,7 @@ bool Image::isImageTranslucent() const case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT): case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT): case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT): - return dxtc_tool::CompressedImageTranslucent(_s, _t, _pixelFormat, _data); + return dxtc_tool::isCompressedImageTranslucent(_s, _t, _pixelFormat, _data); default: return false; } @@ -1919,6 +1919,12 @@ Vec4 _readColor(GLenum pixelFormat, T* data,float scale) Vec4 Image::getColor(unsigned int s,unsigned t,unsigned r) const { + if (dxtc_tool::isDXTC(_pixelFormat)) { + unsigned char color[4]; + if (dxtc_tool::CompressedImageGetColor(color, s, t, r, _s, _t, _r, _pixelFormat, _data)) { + return Vec4(((float)color[0]) / 255.0f, ((float)color[1]) / 255.0f, ((float)color[2]) / 255.0f, ((float)color[3]) / 255.0f ); + } + } const unsigned char* ptr = data(s,t,r); switch(_dataType) diff --git a/src/osg/dxtctool.cpp b/src/osg/dxtctool.cpp index 7e486972a..b8f9ed2b6 100644 --- a/src/osg/dxtctool.cpp +++ b/src/osg/dxtctool.cpp @@ -166,11 +166,28 @@ struct DXT1TexelsBlock unsigned short color_1; // extreme unsigned int texels4x4; // interpolated colors (2 bits per texel) }; - -bool CompressedImageTranslucent(size_t width, size_t height, GLenum format, void * imageData) +struct DXT3TexelsBlock { - // OSG_NOTICE<<"CompressedImageTranslucent("<> 2) * ((height + 3) >> 2); switch(format) { case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT): @@ -182,9 +199,8 @@ bool CompressedImageTranslucent(size_t width, size_t height, GLenum format, void // Only do the check on the first mipmap level, and stop when we // see the first alpha texel - int i = (width*height)/16; - bool foundAlpha = false; - while ((!foundAlpha) && (i>0)) + int i = blockCount; + while (i>0) { // See if this block might contain transparent texels if (texelsBlock->color_0<=texelsBlock->color_1) @@ -192,7 +208,7 @@ bool CompressedImageTranslucent(size_t width, size_t height, GLenum format, void // Scan the texels block for the '11' bit pattern that // indicates a transparent texel int j = 0; - while ((!foundAlpha) && (j < 32)) + while (j < 32) { // Check for the '11' bit pattern on this texel if ( ((texelsBlock->texels4x4 >> j) & 0x03) == 0x03) @@ -214,11 +230,67 @@ bool CompressedImageTranslucent(size_t width, size_t height, GLenum format, void } case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT): - return true; - + { + const DXT3TexelsBlock *texelsBlock = reinterpret_cast(imageData); + // Only do the check on the first mipmap level, and stop when we see the first alpha texel + int i = blockCount; + while (i>0) + { + for (int j =0; j < 4; ++j) + if ( texelsBlock->alpha4[j] != 0xFFFF) //4 pixels at once + return true; //not fully opaque + // Next block + --i; + ++texelsBlock; + } + return false; + } case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT): - return true; + { + const DXT5TexelsBlock *texelsBlock = reinterpret_cast(imageData); + // Only do the check on the first mipmap level, and stop when we see the first alpha texel + int i = blockCount; + unsigned char alphaBlock[8]; + while (i>0) + { + bool eightStep = texelsBlock->alpha_0 > texelsBlock->alpha_1; + alphaBlock[0] = texelsBlock->alpha_0; + alphaBlock[1] = texelsBlock->alpha_1; + if (eightStep) { + if (texelsBlock->alpha_0 < 255) return true; //not fully opaque + alphaBlock[2] = (6 * alphaBlock[0] + 1 * alphaBlock[1] + 3) / 7; // bit code 010 + alphaBlock[3] = (5 * alphaBlock[0] + 2 * alphaBlock[1] + 3) / 7; // bit code 011 + alphaBlock[4] = (4 * alphaBlock[0] + 3 * alphaBlock[1] + 3) / 7; // bit code 100 + alphaBlock[5] = (3 * alphaBlock[0] + 4 * alphaBlock[1] + 3) / 7; // bit code 101 + alphaBlock[6] = (2 * alphaBlock[0] + 5 * alphaBlock[1] + 3) / 7; // bit code 110 + alphaBlock[7] = (1 * alphaBlock[0] + 6 * alphaBlock[1] + 3) / 7; // bit code 111 + } else { + alphaBlock[2] = (4 * alphaBlock[0] + 1 * alphaBlock[1] + 2) / 5; // bit code 010 + alphaBlock[3] = (3 * alphaBlock[0] + 2 * alphaBlock[1] + 2) / 5; // bit code 011 + alphaBlock[4] = (2 * alphaBlock[0] + 3 * alphaBlock[1] + 2) / 5; // bit code 100 + alphaBlock[5] = (1 * alphaBlock[0] + 4 * alphaBlock[1] + 2) / 5; // bit code 101 + alphaBlock[6] = 0; // bit code 110 + alphaBlock[7] = 255; // bit code 111 + } + int last_added_byte = 1; + unsigned short running_a_index = texelsBlock->alpha3[0] + (((unsigned short)texelsBlock->alpha3[last_added_byte]) << 8); + for (int j = 0; j < 16; ++j) { + unsigned char alphaIndex = running_a_index & 0x7; + if (alphaBlock[alphaIndex] < 255) return true; //not fully opaque + running_a_index >>= 3; + if ((3 * j / 8) == last_added_byte) { + ++last_added_byte; + //(&texelsBlock->alpha3[0]) to avoid gcc warning: array subscript is above array bounds [-Warray-bounds] + running_a_index += (((unsigned short)(&(texelsBlock->alpha3[0]))[last_added_byte]) << (8 - (3 * j & 0x7))); + } + } + // Next block + --i; + ++texelsBlock; + } + return false; + } default: break; } @@ -226,4 +298,361 @@ bool CompressedImageTranslucent(size_t width, size_t height, GLenum format, void return false; } +unsigned short interpolateColors21(unsigned short color1, unsigned short color2) { + unsigned short result = (((color1 >> 11) * 2 + (color2 >> 11) + 1) / 3) << 11; + result += (((color1 >> 5 & 0x3F) * 2 + (color2 >> 5 & 0x3F) + 1) / 3) << 5; + result += (((color1 & 0x1F) * 2 + (color2 & 0x1F) + 1) / 3); + return result; +} +unsigned short interpolateColors11(unsigned short color1, unsigned short color2) { + unsigned short result = (((color1 >> 11) + (color2 >> 11) ) / 2) << 11; + result += (((color1 >> 5 & 0x3F) + (color2 >> 5 & 0x3F)) / 2) << 5; + result += (((color1 & 0x1F) + (color2 & 0x1F) ) / 2); + return result; +} + +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) +{ + unsigned short color16 = 0;//RGB 5:6:5 format + + + unsigned int slab4Count = (depth & ~0x3); //4*floor(d/4) + unsigned int col = (s >> 2);//(floor(x/4) + unsigned int row = (t >> 2);//(floor(y/4) + unsigned int blockWidth = (width + 3) >> 2;//ceil(w/4) + unsigned int blockHeight = (height + 3) >> 2;//ceil(h/4) + int blockNumber = col + blockWidth * row ; // block to jump to + + if (depth > 1) { +// https://www.opengl.org/registry/specs/NV/texture_compression_vtc.txt +// if (z >= 4*floor(d/4)) { +// 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)) )); +// } else { +// blockIndex = blocksize * 4 * (floor(x/4) + ceil(w/4) * (floor(y/4) + ceil(h/4) * floor(z/4))); +// } +// note floor(a/4) = (a >> 2) +// note 4*floor(a/4) = a & ~0x3 +// note ceil(a/4) = ((a + 3) >> 2) +// +// rewrite: this describes the final blocks as consecutive 4x4x1 blocks - and thats not in the wording of the specs +// if (r >= slab4Count) { +// blockNumber = (blockWidth * blockHeight * slab4Count + col + blockWidth * (row + blockHeight * (r-slab4Count) )); +// } else { +// blockNumber = 4 * (col + blockWidth * (row + blockHeight * (r >> 2)) ); +// } + +// or in the version of the openGL specs: +// if (z >= 4*floor(d/4)) { +// 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) ); +// } else { +// blockIndex = blocksize * 4 * (floor(x/4) + ceil(w/4) * (floor(y/4) + ceil(h/4) * floor(z/4))); +// } + + unsigned int sub_r = r & 0x3;//(r-slab4Count) + if (r >= slab4Count) { //slice number beyond 4x4x4 slabs + unsigned int blockDepth = depth & 0x3;// equals: depth - slab4Count;//depth of this final block: 1/2/3 in case of 4x4x1; 4x4x2 or 4x4x3 bricks + blockNumber = (blockWidth * blockHeight * slab4Count //jump full 4x4x4 slabs + + blockDepth * ( col + blockWidth * row ) + + sub_r); + } else { + blockNumber = 4 * (col + blockWidth * (row + blockHeight * (r >> 2)) ) + sub_r; + } + } + + int sub_s = s & 0x3; + int sub_t = t & 0x3; + switch (format) + { + case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT) : + case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) : + { + const DXT1TexelsBlock *texelsBlock = reinterpret_cast(imageData); + texelsBlock += blockNumber; //jump to block + char index = (texelsBlock->texels4x4 >> (2 * sub_s + 8 * sub_t)) & 0x3; //two bit "index value" + color[3] = 255; + switch (index) { + case 0: + color16 = texelsBlock->color_0; + break; + case 1: + color16 = texelsBlock->color_1; + break; + case 2: + if (texelsBlock->color_0 > texelsBlock->color_1) { + color16 = interpolateColors21(texelsBlock->color_0, texelsBlock->color_1); + } + else { + color16 = interpolateColors11(texelsBlock->color_0, texelsBlock->color_1); + } + break; + case 3: + if (texelsBlock->color_0 > texelsBlock->color_1) { + color16 = interpolateColors21(texelsBlock->color_1, texelsBlock->color_0); + } + else { + color16 = 0;//black + if (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) color[3] = 0;//transparent + } + break; + } + break; + } + case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) : + { + const DXT3TexelsBlock *texelsBlock = reinterpret_cast(imageData); + texelsBlock += blockNumber; //jump to block + color[3] = 17 * (texelsBlock->alpha4[sub_t] >> 4 * sub_s & 0xF); + char index = (texelsBlock->texels4x4 >> (2 * sub_s + 8 * sub_t)) & 0x3; //two bit "index value" + switch (index) { + case 0: + color16 = texelsBlock->color_0; + break; + case 1: + color16 = texelsBlock->color_1; + break; + case 2: + color16 = interpolateColors21(texelsBlock->color_0, texelsBlock->color_1); + break; + case 3: + color16 = interpolateColors21(texelsBlock->color_1, texelsBlock->color_0); + break; + } + break; + } + case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) : + { + const DXT5TexelsBlock *texelsBlock = reinterpret_cast(imageData); + texelsBlock += blockNumber; //jump to block + char index = (texelsBlock->texels4x4 >> (2 * sub_s + 8 * sub_t)) & 0x3; //two bit "index value" + switch (index) { + case 0: + color16 = texelsBlock->color_0; + break; + case 1: + color16 = texelsBlock->color_1; + break; + case 2: + color16 = interpolateColors21(texelsBlock->color_0, texelsBlock->color_1); + break; + case 3: + color16 = interpolateColors21(texelsBlock->color_1, texelsBlock->color_0); + break; + } + char pixel = sub_s + 4 * sub_t;//pixel number in block: 0 - 15 + char firstBit = 3 * pixel;//least significant bit: range 0 - 45 + unsigned char alpha_index; + if ((firstBit & 0x7) < 6) { + alpha_index = texelsBlock->alpha3[firstBit >> 3] >> (firstBit & 0x7) & 0x7;//grab byte containing least significant bit; shift and get 3 bits + } else { + alpha_index = texelsBlock->alpha3[firstBit >> 3] >> (firstBit & 0x7); + alpha_index |= texelsBlock->alpha3[1 + (firstBit >> 3)] << (8 - (firstBit & 0x7)); + alpha_index &= 0x7; + } + if (alpha_index == 0) { + color[3] = texelsBlock->alpha_0; + } else { + if (alpha_index == 1) { + color[3] = texelsBlock->alpha_1; + } else { + if (texelsBlock->alpha_0 > texelsBlock->alpha_1) { + color[3] = ((unsigned short)texelsBlock->alpha_0 * (8 - alpha_index) + (unsigned short)texelsBlock->alpha_1 * (alpha_index - 1) + 3) / 7; + } else { + if (alpha_index < 6) { + color[3] = ((unsigned short)texelsBlock->alpha_0 * (6 - alpha_index) + (unsigned short)texelsBlock->alpha_1 * (alpha_index - 1) + 3) / 5; + } else { + if (alpha_index == 6) { + color[3] = 0; + } else { + color[3] = 255; + } + } + } + } + } + break; + } + default: + return false; + } + unsigned short colorChannel = color16 >> 11;//red - 5 bits + color[0] = colorChannel << 3 | colorChannel >> 2 ; + colorChannel = color16 >> 5 & 0x3F;//green - 6 bits + color[1] = colorChannel << 2 | colorChannel >> 3; + colorChannel = color16 & 0x1F;//blue - 5 bits + color[2] = colorChannel << 3 | colorChannel >> 2; + return true; +} +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) +{ + unsigned int src_texels4x4; + unsigned int *dst_texels4x4 = NULL; + switch (format) + { + case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT) : + case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) : + { + const DXT1TexelsBlock *src_texelsBlock = reinterpret_cast(src_block); + //make a copy as source might be equal to destination + src_texels4x4 = src_texelsBlock->texels4x4; // interpolated colors (2 bits per texel) + DXT1TexelsBlock *dst_texelsBlock = reinterpret_cast(dst_block); + dst_texels4x4 = &dst_texelsBlock->texels4x4; + + break; + } + case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) : + { + const DXT3TexelsBlock *src_texelsBlock = reinterpret_cast(src_block); + //make a copy as source might be equal to destination + src_texels4x4 = src_texelsBlock->texels4x4; // interpolated colors (2 bits per texel) + DXT3TexelsBlock *dst_texelsBlock = reinterpret_cast(dst_block); + dst_texels4x4 = &dst_texelsBlock->texels4x4; + unsigned short src_alpha4[4]; // alpha values (4 bits per texel) - 64 bits + + memcpy(src_alpha4, src_texelsBlock->alpha4, 4 * sizeof(unsigned short));//make a copy as source might be equal to destination + + memset(dst_texelsBlock->alpha4, 0, 4 * sizeof(unsigned short)); //clear + osg::Vec3i source_pixel(srcOrigin); + for (int r = 0; r<4; r++)//rows + { + for (int c = 0; c<4; c++)//columns + { + int sub_s = source_pixel.x() & 0x3; + int sub_t = source_pixel.y() & 0x3; + int shiftBits = 4 * sub_s; + unsigned int alpha_value = src_alpha4[sub_t] >> shiftBits & 0xf; //four bit alpha values + + shiftBits = 4 * c;//destination + alpha_value <<= shiftBits; + dst_texelsBlock->alpha4[r] |= alpha_value; + + source_pixel = source_pixel + rowDelta; + } + source_pixel = source_pixel + columnDelta; + } + break; + } + case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) : + { + const DXT5TexelsBlock *src_texelsBlock = reinterpret_cast(src_block); + //make a copy as source might be equal to destination + src_texels4x4 = src_texelsBlock->texels4x4; // interpolated colors (2 bits per texel) + DXT5TexelsBlock *dst_texelsBlock = reinterpret_cast(dst_block); + dst_texels4x4 = &dst_texelsBlock->texels4x4; + + unsigned char src_alpha3[6]; // alpha index values (3 bits per texel) + + memcpy(src_alpha3, src_texelsBlock->alpha3, 6 * sizeof(unsigned char));//make a copy as source might be equal to destination + + memset(dst_texelsBlock->alpha3, 0, 6 * sizeof(unsigned char)); //clear + osg::Vec3i source_pixel(srcOrigin); + unsigned int last_added_byte = 1; + unsigned short running_a_index = src_texelsBlock->alpha3[0] + (((unsigned short)src_texelsBlock->alpha3[last_added_byte]) << 8); + unsigned int j = 0; + for (int r = 0; r<4; r++)//rows + { + for (int c = 0; c<4; c++)//columns + { + int sub_s = source_pixel.x() & 0x3; + int sub_t = source_pixel.y() & 0x3; + + unsigned char alphaIndex = running_a_index & 0x7; + //store alphaIndex in output position: + int shiftBits = 3 * sub_s + 12 * sub_t;//LSB + dst_texelsBlock->alpha3[shiftBits >> 3] |= alphaIndex << (shiftBits & 0x7); + if ((shiftBits & 0x7) > 5) { + dst_texelsBlock->alpha3[1 + (shiftBits >> 3)] |= alphaIndex >> (8 - (shiftBits & 0x7)); + } + + running_a_index >>= 3; + if ((3 * ++j / 8) == last_added_byte) { + ++last_added_byte; + //(&texelsBlock->alpha3[0]) to avoid gcc warning: array subscript is above array bounds [-Warray-bounds] + running_a_index += (((unsigned short)(&(src_texelsBlock->alpha3[0]))[last_added_byte]) << (8 - (3 * j & 0x7))); + } + source_pixel = source_pixel + rowDelta; + } + source_pixel = source_pixel + columnDelta; + } + break; + } + default: + return; + }//switch + + //all formats: rearrange the colors + *dst_texels4x4 = 0;//clear + osg::Vec3i source_pixel(srcOrigin); + for (int r = 0; r<4; r++)//rows + { + for (int c = 0; c<4; c++)//columns + { + int sub_s = source_pixel.x() & 0x3; + int sub_t = source_pixel.y() & 0x3; + int shiftBits = 2 * sub_s + 8 * sub_t; + unsigned int index = (src_texels4x4 >> (shiftBits)) & 0x3; //two bit "index value" + + shiftBits = 2 * c + 8 * r;//destination + index <<= shiftBits; + *dst_texels4x4 |= index; + + source_pixel = source_pixel + rowDelta; + } + source_pixel = source_pixel + columnDelta; + } +} + +void compressedBlockStripAlhpa(const GLenum format, const unsigned char *src_block, unsigned char *dst_block) { + unsigned int src_texels4x4; + char reshuffle[4] = { 1, 0, 3, 2 }; + switch (format) + { + default: + case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT) : + case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) : + { + const DXT1TexelsBlock *src_texelsBlock = reinterpret_cast(src_block); + //make a copy as source might be equal to destination + src_texels4x4 = src_texelsBlock->texels4x4; // interpolated colors (2 bits per texel) + DXT1TexelsBlock *dst_texelsBlock = reinterpret_cast(dst_block); + if (src_texelsBlock->color_0 > src_texelsBlock->color_1) { + // Four-color block + memcpy(dst_texelsBlock, src_texelsBlock, sizeof(DXT1TexelsBlock)); + } else { + dst_texelsBlock->color_0 = src_texelsBlock->color_1; + dst_texelsBlock->color_1 = src_texelsBlock->color_0; + dst_texelsBlock->texels4x4 = 0; + for (unsigned int shiftBits = 0; shiftBits < 32; shiftBits += 2) { + unsigned char index = src_texels4x4 >> shiftBits & 0x3; //two bit "index value" + dst_texelsBlock->texels4x4 |= reshuffle[index] << shiftBits; + } + + } + break; + } + case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT) : + case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) : + { + const DXT3TexelsBlock *src_texelsBlock = reinterpret_cast(src_block); + //make a copy as source might be equal to destination + src_texels4x4 = src_texelsBlock->texels4x4; // interpolated colors (2 bits per texel) + DXT1TexelsBlock *dst_texelsBlock = reinterpret_cast(dst_block); + if (src_texelsBlock->color_0 > src_texelsBlock->color_1) { + // Four-color block + memcpy(dst_texelsBlock, src_texelsBlock, sizeof(DXT3TexelsBlock)); + } + else { + dst_texelsBlock->color_0 = src_texelsBlock->color_1; + dst_texelsBlock->color_1 = src_texelsBlock->color_0; + dst_texelsBlock->texels4x4 = 0; + for (unsigned int shiftBits = 0; shiftBits < 32; shiftBits += 2) { + unsigned char index = src_texels4x4 >> shiftBits & 0x3; //two bit "index value" + dst_texelsBlock->texels4x4 |= reshuffle[index] << shiftBits; + + } + + } + break; + } + } +} } // namespace dxtc_tool diff --git a/src/osg/dxtctool.h b/src/osg/dxtctool.h index f24cf9c90..304399d99 100644 --- a/src/osg/dxtctool.h +++ b/src/osg/dxtctool.h @@ -31,17 +31,18 @@ // Current version: 1.00 BETA 1 (27/08/2002) // // Comment: Only works with DXTC mode supported by OpenGL. -// (currently: DXT1/DXT3/DXT5) +// (currently: DXT1/DXT3/DXT5) // // History: - // ////////////////////////////////////////////////////////////////////// #ifndef DXTCTOOL_H -#define DXTCTOOL_H +#define DXTCTOOL_H #include #include +#include #if defined(_MSC_VER) @@ -78,10 +79,19 @@ bool isDXTC(GLenum pixelFormat); bool VerticalFlip(size_t Width, size_t Height, GLenum Format, void * pPixels); -bool CompressedImageTranslucent(size_t Width, size_t Height, GLenum Format, void * pPixels); +bool isCompressedImageTranslucent(size_t Width, size_t Height, GLenum Format, void * pPixels); +//interpolate RGB565 colors with 2/3 part color1 and 1/3 part color2 +unsigned short interpolateColors21(unsigned short color1, unsigned short color2); +//interpolate RGB565 colors with equal weights +unsigned short interpolateColors11(unsigned short color1, unsigned short color2); -// Class holding reference to DXTC image pixels +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); + +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); + +void compressedBlockStripAlhpa(const GLenum format, const unsigned char *src_block, unsigned char *dst_block); +// Class holding reference to DXTC image pixels class dxtc_pixels { public: @@ -102,7 +112,7 @@ protected: inline bool SupportedFormat() const; // Vertical flipping functions - void VFlip_DXT1() const; + void VFlip_DXT1() const; void VFlip_DXT3() const; void VFlip_DXT5() const; @@ -116,7 +126,7 @@ protected: inline void BVF_Alpha_DXT5_H2(void * const pBlock) const; // V. flip one alpha (DXT5) block with its virtual height == 2 inline void BVF_Alpha_DXT5_H4(void * const pBlock) const; // V. flip one alpha (DXT5) block with its virtual height == 4 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 - + // Block localization functions inline void * GetBlock(size_t i, size_t j, size_t BlockSize) const; @@ -155,7 +165,7 @@ inline bool isDXTC(GLenum pixelFormat) } inline bool VerticalFlip(size_t Width, size_t Height, GLenum Format, void * pPixels) { - return (dxtc_pixels(Width, Height, Format, pPixels)).VFlip(); + return (dxtc_pixels(Width, Height, Format, pPixels)).VFlip(); }