Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/WolfireGames/overgrowth.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Images/nv_image_dds.cpp')
-rw-r--r--Source/Images/nv_image_dds.cpp663
1 files changed, 663 insertions, 0 deletions
diff --git a/Source/Images/nv_image_dds.cpp b/Source/Images/nv_image_dds.cpp
new file mode 100644
index 00000000..8db8922e
--- /dev/null
+++ b/Source/Images/nv_image_dds.cpp
@@ -0,0 +1,663 @@
+//-----------------------------------------------------------------------------
+// Name: nv_image_dds.h
+// Developer: Wolfire Games LLC
+// Description: This is a file from an Nvidia image library, with some
+// modification made by Wolfire.
+// License: Read below
+//-----------------------------------------------------------------------------
+//
+// nvImageDDS.cpp - Image support class
+//
+// The nvImage class implements an interface for a multipurpose image
+// object. This class is useful for loading and formating images
+// for use as textures. The class supports dds, png, and hdr formats.
+//
+// This file implements the DDS specific functionality.
+//
+// Author: Evan Hart
+// Email: sdkfeedback@nvidia.com
+//
+// Copyright (c) NVIDIA Corporation. All rights reserved.
+////////////////////////////////////////////////////////////////////////////////
+
+#include <Images/nv_image.h>
+#include <Compat/fileio.h>
+#include <Internal/integer.h>
+
+#include <cstdio>
+#include <cstring>
+
+using std::vector;
+
+namespace nv2 {
+
+//
+// Structure defines and constants from nvdds
+//
+//////////////////////////////////////////////////////////////////////
+
+// surface description flags
+const uint32_t DDSF_CAPS = 0x00000001l;
+const uint32_t DDSF_HEIGHT = 0x00000002l;
+const uint32_t DDSF_WIDTH = 0x00000004l;
+const uint32_t DDSF_PITCH = 0x00000008l;
+const uint32_t DDSF_PIXELFORMAT = 0x00001000l;
+const uint32_t DDSF_MIPMAPCOUNT = 0x00020000l;
+const uint32_t DDSF_LINEARSIZE = 0x00080000l;
+const uint32_t DDSF_DEPTH = 0x00800000l;
+
+// pixel format flags
+const uint32_t DDSF_ALPHAPIXELS = 0x00000001l;
+const uint32_t DDSF_FOURCC = 0x00000004l;
+const uint32_t DDSF_RGB = 0x00000040l;
+const uint32_t DDSF_RGBA = 0x00000041l;
+
+// dwCaps1 flags
+const uint32_t DDSF_COMPLEX = 0x00000008l;
+const uint32_t DDSF_TEXTURE = 0x00001000l;
+const uint32_t DDSF_MIPMAP = 0x00400000l;
+
+// dwCaps2 flags
+const uint32_t DDSF_CUBEMAP = 0x00000200l;
+const uint32_t DDSF_CUBEMAP_POSITIVEX = 0x00000400l;
+const uint32_t DDSF_CUBEMAP_NEGATIVEX = 0x00000800l;
+const uint32_t DDSF_CUBEMAP_POSITIVEY = 0x00001000l;
+const uint32_t DDSF_CUBEMAP_NEGATIVEY = 0x00002000l;
+const uint32_t DDSF_CUBEMAP_POSITIVEZ = 0x00004000l;
+const uint32_t DDSF_CUBEMAP_NEGATIVEZ = 0x00008000l;
+const uint32_t DDSF_CUBEMAP_ALL_FACES = 0x0000FC00l;
+const uint32_t DDSF_VOLUME = 0x00200000l;
+
+// compressed texture types
+const uint32_t FOURCC_UNKNOWN = 0;
+
+#ifndef MAKEFOURCC
+#define MAKEFOURCC(c0,c1,c2,c3) \
+ ((uint32_t)(unsigned char)(c0)| \
+ ((uint32_t)(unsigned char)(c1) << 8)| \
+ ((uint32_t)(unsigned char)(c2) << 16)| \
+ ((uint32_t)(unsigned char)(c3) << 24))
+#endif
+
+const uint32_t FOURCC_R8G8B8 = 20;
+const uint32_t FOURCC_A8R8G8B8 = 21;
+const uint32_t FOURCC_X8R8G8B8 = 22;
+const uint32_t FOURCC_R5G6B5 = 23;
+const uint32_t FOURCC_X1R5G5B5 = 24;
+const uint32_t FOURCC_A1R5G5B5 = 25;
+const uint32_t FOURCC_A4R4G4B4 = 26;
+const uint32_t FOURCC_R3G3B2 = 27;
+const uint32_t FOURCC_A8 = 28;
+const uint32_t FOURCC_A8R3G3B2 = 29;
+const uint32_t FOURCC_X4R4G4B4 = 30;
+const uint32_t FOURCC_A2B10G10R10 = 31;
+const uint32_t FOURCC_A8B8G8R8 = 32;
+const uint32_t FOURCC_X8B8G8R8 = 33;
+const uint32_t FOURCC_G16R16 = 34;
+const uint32_t FOURCC_A2R10G10B10 = 35;
+const uint32_t FOURCC_A16B16G16R16 = 36;
+
+const uint32_t FOURCC_L8 = 50;
+const uint32_t FOURCC_A8L8 = 51;
+const uint32_t FOURCC_A4L4 = 52;
+const uint32_t FOURCC_DXT1 = 0x31545844l; //(MAKEFOURCC('D','X','T','1'))
+const uint32_t FOURCC_DXT2 = 0x32545844l; //(MAKEFOURCC('D','X','T','1'))
+const uint32_t FOURCC_DXT3 = 0x33545844l; //(MAKEFOURCC('D','X','T','3'))
+const uint32_t FOURCC_DXT4 = 0x34545844l; //(MAKEFOURCC('D','X','T','3'))
+const uint32_t FOURCC_DXT5 = 0x35545844l; //(MAKEFOURCC('D','X','T','5'))
+const uint32_t FOURCC_ATI1 = MAKEFOURCC('A','T','I','1');
+const uint32_t FOURCC_ATI2 = MAKEFOURCC('A','T','I','2');
+
+const uint32_t FOURCC_D16_LOCKABLE = 70;
+const uint32_t FOURCC_D32 = 71;
+const uint32_t FOURCC_D24X8 = 77;
+const uint32_t FOURCC_D16 = 80;
+
+const uint32_t FOURCC_D32F_LOCKABLE = 82;
+
+const uint32_t FOURCC_L16 = 81;
+
+// Floating point surface formats
+
+// s10e5 formats (16-bits per channel)
+const uint32_t FOURCC_R16F = 111;
+const uint32_t FOURCC_G16R16F = 112;
+const uint32_t FOURCC_A16B16G16R16F = 113;
+
+// IEEE s23e8 formats (32-bits per channel)
+const uint32_t FOURCC_R32F = 114;
+const uint32_t FOURCC_G32R32F = 115;
+const uint32_t FOURCC_A32B32G32R32F = 116;
+
+struct DXTColBlock
+{
+ GLushort col0;
+ GLushort col1;
+
+ GLubyte row[4];
+};
+
+struct DXT3AlphaBlock
+{
+ GLushort row[4];
+};
+
+struct DXT5AlphaBlock
+{
+ GLubyte alpha0;
+ GLubyte alpha1;
+
+ GLubyte row[6];
+};
+
+struct DDS_PIXELFORMAT
+{
+ uint32_t dwSize;
+ uint32_t dwFlags;
+ uint32_t dwFourCC;
+ uint32_t dwRGBBitCount;
+ uint32_t dwRBitMask;
+ uint32_t dwGBitMask;
+ uint32_t dwBBitMask;
+ uint32_t dwABitMask;
+};
+
+struct DDS_HEADER
+{
+ uint32_t dwSize;
+ uint32_t dwFlags;
+ uint32_t dwHeight;
+ uint32_t dwWidth;
+ uint32_t dwPitchOrLinearSize;
+ uint32_t dwDepth;
+ uint32_t dwMipMapCount;
+ uint32_t dwReserved1[11];
+ DDS_PIXELFORMAT ddspf;
+ uint32_t dwCaps1;
+ uint32_t dwCaps2;
+ uint32_t dwReserved2[3];
+};
+
+//
+//
+////////////////////////////////////////////////////////////
+bool Image::readDDS( const char *file, Image& i) {
+
+ // open file
+ FILE *fp = my_fopen(file, "rb");
+ if (fp == NULL)
+ return false;
+
+ // read in file marker, make sure its a DDS file
+ char filecode[4];
+ fread(filecode, 1, 4, fp);
+ if (strncmp(filecode, "DDS ", 4) != 0)
+ {
+ fclose(fp);
+ return false;
+ }
+
+ // read in DDS header
+ DDS_HEADER ddsh;
+ fread(&ddsh, sizeof(DDS_HEADER), 1, fp);
+
+ // check if image is a volume texture
+ if ((ddsh.dwCaps2 & DDSF_VOLUME) && (ddsh.dwDepth > 0))
+ i._depth = ddsh.dwDepth;
+ else
+ i._depth = 0;
+
+ // There are flags that are supposed to mark these fields as valid, but some dds files don't set them properly
+ i._width = ddsh.dwWidth;
+ i._height = ddsh.dwHeight;
+
+ if (ddsh.dwFlags & DDSF_MIPMAPCOUNT) {
+ i._levelCount = ddsh.dwMipMapCount;
+ }
+ else
+ i._levelCount = 1;
+
+ //check cube-map faces
+ if ( ddsh.dwCaps2 & DDSF_CUBEMAP) {
+ //this is a cubemap, count the faces
+ i._faces = 0;
+ i._faces += (ddsh.dwCaps2 & DDSF_CUBEMAP_POSITIVEX) ? 1 : 0;
+ i._faces += (ddsh.dwCaps2 & DDSF_CUBEMAP_NEGATIVEX) ? 1 : 0;
+ i._faces += (ddsh.dwCaps2 & DDSF_CUBEMAP_POSITIVEY) ? 1 : 0;
+ i._faces += (ddsh.dwCaps2 & DDSF_CUBEMAP_NEGATIVEY) ? 1 : 0;
+ i._faces += (ddsh.dwCaps2 & DDSF_CUBEMAP_POSITIVEZ) ? 1 : 0;
+ i._faces += (ddsh.dwCaps2 & DDSF_CUBEMAP_NEGATIVEZ) ? 1 : 0;
+
+ //check for a complete cubemap
+ if ( (i._faces != 6) || (i._width != i._height) ) {
+ fclose(fp);
+ return false;
+ }
+ }
+ else {
+ //not a cubemap
+ i._faces = 0;
+ }
+
+ bool btcCompressed = false;
+ int bytesPerElement = 0;
+
+ // figure out what the image format is
+ if (ddsh.ddspf.dwFlags & DDSF_FOURCC)
+ {
+ switch(ddsh.ddspf.dwFourCC)
+ {
+ case FOURCC_DXT1:
+ i._format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ i._internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ i._type = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ bytesPerElement = 8;
+ btcCompressed = true;
+ break;
+
+ case FOURCC_DXT2:
+ case FOURCC_DXT3:
+ i._format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ i._internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ i._type = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ bytesPerElement = 16;
+ btcCompressed = true;
+ break;
+
+ case FOURCC_DXT4:
+ case FOURCC_DXT5:
+ i._format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ i._internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ i._type = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ bytesPerElement = 16;
+ btcCompressed = true;
+ break;
+
+ case FOURCC_ATI1:
+ i._format = GL_COMPRESSED_LUMINANCE_LATC1_EXT;
+ i._internalFormat = GL_COMPRESSED_LUMINANCE_LATC1_EXT;
+ i._type = GL_COMPRESSED_LUMINANCE_LATC1_EXT;
+ bytesPerElement = 8;
+ btcCompressed = true;
+ break;
+
+ case FOURCC_ATI2:
+ i._format = GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
+ i._internalFormat = GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
+ i._type = GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
+ bytesPerElement = 16;
+ btcCompressed = true;
+ break;
+
+ case FOURCC_R8G8B8:
+ i._format = GL_BGR;
+ i._internalFormat = GL_RGB8;
+ i._type = GL_UNSIGNED_BYTE;
+ bytesPerElement = 3;
+ break;
+
+ case FOURCC_A8R8G8B8:
+ i._format = GL_BGRA;
+ i._internalFormat = GL_RGBA8;
+ i._type = GL_UNSIGNED_BYTE;
+ bytesPerElement = 4;
+ break;
+
+ case FOURCC_X8R8G8B8:
+ i._format = GL_BGRA;
+ i._internalFormat = GL_RGB8;
+ i._type = GL_UNSIGNED_INT_8_8_8_8;
+ bytesPerElement = 4;
+ break;
+
+ case FOURCC_R5G6B5:
+ i._format = GL_BGR;
+ i._internalFormat = GL_RGB5;
+ i._type = GL_UNSIGNED_SHORT_5_6_5;
+ bytesPerElement = 2;
+ break;
+
+ case FOURCC_A8:
+ i._format = GL_ALPHA;
+ i._internalFormat = GL_ALPHA8;
+ i._type = GL_UNSIGNED_BYTE;
+ bytesPerElement = 1;
+ break;
+
+ case FOURCC_A2B10G10R10:
+ i._format = GL_RGBA;
+ i._internalFormat = GL_RGB10_A2;
+ i._type = GL_UNSIGNED_INT_10_10_10_2;
+ bytesPerElement = 4;
+ break;
+
+ case FOURCC_A8B8G8R8:
+ i._format = GL_RGBA;
+ i._internalFormat = GL_RGBA8;
+ i._type = GL_UNSIGNED_BYTE;
+ bytesPerElement = 4;
+ break;
+
+ case FOURCC_X8B8G8R8:
+ i._format = GL_RGBA;
+ i._internalFormat = GL_RGB8;
+ i._type = GL_UNSIGNED_INT_8_8_8_8;
+ bytesPerElement = 4;
+ break;
+
+ case FOURCC_A2R10G10B10:
+ i._format = GL_BGRA;
+ i._internalFormat = GL_RGB10_A2;
+ i._type = GL_UNSIGNED_INT_10_10_10_2;
+ bytesPerElement = 4;
+ break;
+
+ case FOURCC_A16B16G16R16:
+ i._format = GL_RGBA;
+ i._internalFormat = GL_RGBA16;
+ i._type = GL_UNSIGNED_SHORT;
+ bytesPerElement = 8;
+ break;
+
+ case FOURCC_L8:
+ i._format = GL_LUMINANCE;
+ i._internalFormat = GL_LUMINANCE8;
+ i._type = GL_UNSIGNED_BYTE;
+ bytesPerElement = 1;
+ break;
+
+ case FOURCC_A8L8:
+ i._format = GL_LUMINANCE_ALPHA;
+ i._internalFormat = GL_LUMINANCE8_ALPHA8;
+ i._type = GL_UNSIGNED_BYTE;
+ bytesPerElement = 2;
+ break;
+
+ case FOURCC_L16:
+ i._format = GL_LUMINANCE;
+ i._internalFormat = GL_LUMINANCE16;
+ i._type = GL_UNSIGNED_SHORT;
+ bytesPerElement = 2;
+ break;
+
+ case FOURCC_R16F:
+ i._format = GL_LUMINANCE; //should use red, once it is available
+ i._internalFormat = GL_LUMINANCE16F_ARB;
+ i._type = GL_HALF_FLOAT;
+ bytesPerElement = 2;
+ break;
+
+ case FOURCC_A16B16G16R16F:
+ i._format = GL_RGBA;
+ i._internalFormat = GL_RGBA16F_ARB;
+ i._type = GL_HALF_FLOAT;
+ bytesPerElement = 8;
+ break;
+
+ case FOURCC_R32F:
+ i._format = GL_LUMINANCE; //should use red, once it is available
+ i._internalFormat = GL_LUMINANCE32F_ARB;
+ i._type = GL_FLOAT;
+ bytesPerElement = 4;
+ break;
+
+ case FOURCC_A32B32G32R32F:
+ i._format = GL_RGBA;
+ i._internalFormat = GL_RGBA32F;
+ i._type = GL_FLOAT;
+ bytesPerElement = 16;
+ break;
+
+ case FOURCC_UNKNOWN:
+ case FOURCC_X1R5G5B5:
+ case FOURCC_A1R5G5B5:
+ case FOURCC_A4R4G4B4:
+ case FOURCC_R3G3B2:
+ case FOURCC_A8R3G3B2:
+ case FOURCC_X4R4G4B4:
+ case FOURCC_A4L4:
+ case FOURCC_D16_LOCKABLE:
+ case FOURCC_D32:
+ case FOURCC_D24X8:
+ case FOURCC_D16:
+ case FOURCC_D32F_LOCKABLE:
+ case FOURCC_G16R16:
+ case FOURCC_G16R16F:
+ case FOURCC_G32R32F:
+ //these are unsupported for now
+ default:
+ fclose(fp);
+ return false;
+ }
+ }
+ else if (ddsh.ddspf.dwFlags == DDSF_RGBA && ddsh.ddspf.dwRGBBitCount == 32)
+ {
+ i._format = GL_BGRA;
+ i._internalFormat = GL_RGBA8;
+ i._type = GL_UNSIGNED_BYTE;
+ bytesPerElement = 4;
+ }
+ else if (ddsh.ddspf.dwFlags == DDSF_RGB && ddsh.ddspf.dwRGBBitCount == 32)
+ {
+ i._format = GL_BGR;
+ i._internalFormat = GL_RGBA8;
+ i._type = GL_UNSIGNED_BYTE;
+ bytesPerElement = 4;
+ }
+ else if (ddsh.ddspf.dwFlags == DDSF_RGB && ddsh.ddspf.dwRGBBitCount == 24)
+ {
+ i._format = GL_BGR;
+ i._internalFormat = GL_RGB8;
+ i._type = GL_UNSIGNED_BYTE;
+ bytesPerElement = 3;
+ }
+ else if (ddsh.ddspf.dwRGBBitCount == 8)
+ {
+ i._format = GL_LUMINANCE;
+ i._internalFormat = GL_LUMINANCE8;
+ i._type = GL_UNSIGNED_BYTE;
+ bytesPerElement = 1;
+ }
+ else
+ {
+ fclose(fp);
+ return false;
+ }
+
+ i._elementSize = bytesPerElement;
+
+ for (int face = 0; face < ((i._faces) ? i._faces : 1); face++) {
+ int w = i._width, h = i._height, d = (i._depth) ? i._depth : 1;
+ for (int level = 0; level < i._levelCount; level++) {
+ int bw = (btcCompressed) ? (w+3)/4 : w;
+ int bh = (btcCompressed) ? (h+3)/4 : h;
+ int size = bw*bh*d*bytesPerElement;
+
+ GLubyte *data = new GLubyte[size];
+
+ fread( data, size, 1, fp);
+
+ i._data.push_back(data);
+
+ if (i._faces != 6)
+ i.flipSurface( data, w, h, d);
+
+ //reduce mip sizes
+ w = ( w > 1) ? w >> 1 : 1;
+ h = ( h > 1) ? h >> 1 : 1;
+ d = ( d > 1) ? d >> 1 : 1;
+ }
+ }
+/*
+ //reverse cube map y faces
+ if (i._faces == 6) {
+ for (int level = 0; level < i._levelCount; level++) {
+ GLubyte *temp = i._data[2*i._levelCount + level];
+ i._data[2*i._levelCount + level] = i._data[3*i._levelCount + level];
+ i._data[3*i._levelCount + level] = temp;
+ }
+ }
+ */
+
+ fclose(fp);
+ return true;
+}
+
+//
+// flip a DXT1 color block
+////////////////////////////////////////////////////////////
+void Image::flip_blocks_dxtc1(GLubyte *ptr, unsigned int numBlocks)
+{
+ DXTColBlock *curblock = (DXTColBlock*)ptr;
+ GLubyte temp;
+
+ for (unsigned int i = 0; i < numBlocks; i++) {
+ temp = curblock->row[0];
+ curblock->row[0] = curblock->row[3];
+ curblock->row[3] = temp;
+ temp = curblock->row[1];
+ curblock->row[1] = curblock->row[2];
+ curblock->row[2] = temp;
+
+ curblock++;
+ }
+}
+
+//
+// flip a DXT3 color block
+////////////////////////////////////////////////////////////
+void Image::flip_blocks_dxtc3(GLubyte *ptr, unsigned int numBlocks)
+{
+ DXTColBlock *curblock = (DXTColBlock*)ptr;
+ DXT3AlphaBlock *alphablock;
+ GLushort tempS;
+ GLubyte tempB;
+
+ for (unsigned int i = 0; i < numBlocks; i++)
+ {
+ alphablock = (DXT3AlphaBlock*)curblock;
+
+ tempS = alphablock->row[0];
+ alphablock->row[0] = alphablock->row[3];
+ alphablock->row[3] = tempS;
+ tempS = alphablock->row[1];
+ alphablock->row[1] = alphablock->row[2];
+ alphablock->row[2] = tempS;
+
+ curblock++;
+
+ tempB = curblock->row[0];
+ curblock->row[0] = curblock->row[3];
+ curblock->row[3] = tempB;
+ tempB = curblock->row[1];
+ curblock->row[1] = curblock->row[2];
+ curblock->row[2] = tempB;
+
+ curblock++;
+ }
+}
+
+//
+// flip a DXT5 alpha block
+////////////////////////////////////////////////////////////
+void flip_dxt5_alpha(DXT5AlphaBlock *block)
+{
+ GLubyte gBits[4][4];
+
+ const uint32_t mask = 0x00000007; // bits = 00 00 01 11
+ uint32_t bits = 0;
+ memcpy(&bits, &block->row[0], sizeof(unsigned char) * 3);
+
+ gBits[0][0] = (GLubyte)(bits & mask);
+ bits >>= 3;
+ gBits[0][1] = (GLubyte)(bits & mask);
+ bits >>= 3;
+ gBits[0][2] = (GLubyte)(bits & mask);
+ bits >>= 3;
+ gBits[0][3] = (GLubyte)(bits & mask);
+ bits >>= 3;
+ gBits[1][0] = (GLubyte)(bits & mask);
+ bits >>= 3;
+ gBits[1][1] = (GLubyte)(bits & mask);
+ bits >>= 3;
+ gBits[1][2] = (GLubyte)(bits & mask);
+ bits >>= 3;
+ gBits[1][3] = (GLubyte)(bits & mask);
+
+ bits = 0;
+ memcpy(&bits, &block->row[3], sizeof(GLubyte) * 3);
+
+ gBits[2][0] = (GLubyte)(bits & mask);
+ bits >>= 3;
+ gBits[2][1] = (GLubyte)(bits & mask);
+ bits >>= 3;
+ gBits[2][2] = (GLubyte)(bits & mask);
+ bits >>= 3;
+ gBits[2][3] = (GLubyte)(bits & mask);
+ bits >>= 3;
+ gBits[3][0] = (GLubyte)(bits & mask);
+ bits >>= 3;
+ gBits[3][1] = (GLubyte)(bits & mask);
+ bits >>= 3;
+ gBits[3][2] = (GLubyte)(bits & mask);
+ bits >>= 3;
+ gBits[3][3] = (GLubyte)(bits & mask);
+
+ // clear existing alpha bits
+ memset(block->row, 0, sizeof(GLubyte) * 6);
+
+ uint32_t *pBits = ((uint32_t*) &(block->row[0]));
+
+ *pBits = *pBits | (gBits[3][0] << 0);
+ *pBits = *pBits | (gBits[3][1] << 3);
+ *pBits = *pBits | (gBits[3][2] << 6);
+ *pBits = *pBits | (gBits[3][3] << 9);
+
+ *pBits = *pBits | (gBits[2][0] << 12);
+ *pBits = *pBits | (gBits[2][1] << 15);
+ *pBits = *pBits | (gBits[2][2] << 18);
+ *pBits = *pBits | (gBits[2][3] << 21);
+
+ pBits = ((uint32_t*) &(block->row[3]));
+
+ *pBits = *pBits | (gBits[1][0] << 0);
+ *pBits = *pBits | (gBits[1][1] << 3);
+ *pBits = *pBits | (gBits[1][2] << 6);
+ *pBits = *pBits | (gBits[1][3] << 9);
+
+ *pBits = *pBits | (gBits[0][0] << 12);
+ *pBits = *pBits | (gBits[0][1] << 15);
+ *pBits = *pBits | (gBits[0][2] << 18);
+ *pBits = *pBits | (gBits[0][3] << 21);
+}
+
+//
+// flip a DXT5 color block
+////////////////////////////////////////////////////////////
+void Image::flip_blocks_dxtc5(GLubyte *ptr, unsigned int numBlocks)
+{
+ DXTColBlock *curblock = (DXTColBlock*)ptr;
+ DXT5AlphaBlock *alphablock;
+ GLubyte temp;
+
+ for (unsigned int i = 0; i < numBlocks; i++)
+ {
+ alphablock = (DXT5AlphaBlock*)curblock;
+
+ flip_dxt5_alpha(alphablock);
+
+ curblock++;
+
+ temp = curblock->row[0];
+ curblock->row[0] = curblock->row[3];
+ curblock->row[3] = temp;
+ temp = curblock->row[1];
+ curblock->row[1] = curblock->row[2];
+ curblock->row[2] = temp;
+
+ curblock++;
+ }
+}
+
+
+}