#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glaux.h>
#include <ddraw.h>
#include "glext.h"
#define FOURCC_DXT1_REV (MAKEFOURCC('1','T','X','D'))
#define FOURCC_DXT2_REV (MAKEFOURCC('2','T','X','D'))
#define FOURCC_DXT3_REV (MAKEFOURCC('3','T','X','D'))
#define FOURCC_DXT4_REV (MAKEFOURCC('4','T','X','D'))
#define FOURCC_DXT5_REV (MAKEFOURCC('5','T','X','D'))
GLuint loadCompressedTexture(const char *file)
{
GLenum format=0;
int nBlockSize=-1;
GLuint tID = -1;
char *puffer2=0, *p;
bool compressed=false;
int type;
int a,r,g,b,c,d;
if( (file[0]!='D')||(file[1]!='D')||(file[2]!='S') )
{
logger.log( "DDS header error\n");
return -1;
}
DDSURFACEDESC2 &ddsd = *(DDSURFACEDESC2*)(&file[4]);
int nHeight = ddsd.dwHeight;
int nWidth = ddsd.dwWidth;
int nNumMipMaps = ddsd.dwMipMapCount;
switch( ddsd.ddpfPixelFormat.dwFourCC )
{
case FOURCC_DXT1:
case FOURCC_DXT1_REV:
format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
nBlockSize = 8;
compressed=true;
break;
case FOURCC_DXT3:
case FOURCC_DXT3_REV:
format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
nBlockSize = 16;
compressed=true;
break;
case FOURCC_DXT5:
case FOURCC_DXT5_REV:
format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
nBlockSize = 16;
compressed=true;
break;
default:
nNumMipMaps=1;
}
GLubyte *pixels=(GLubyte*)&file[sizeof(ddsd)+4];
if(format==0)
{
switch(ddsd.ddpfPixelFormat.dwRGBBitCount)
{
case 32:
if(!compressed)format=GL_RGBA;
else format = GL_RGBA8;
nBlockSize = 4;
type=GL_UNSIGNED_BYTE;
break;
case 24:
if(!compressed)format=GL_RGB;
else format = GL_RGB8;
type=GL_UNSIGNED_BYTE;
nBlockSize = 3;
break;
case 16:
if(compressed)
{
return -1;
}
else
{
int rmask=ddsd.ddpfPixelFormat.dwRBitMask;
int gmask=ddsd.ddpfPixelFormat.dwGBitMask;
int bmask=ddsd.ddpfPixelFormat.dwBBitMask;
a=rmask & gmask & bmask;
if(a<65535)
{
puffer2=new char[nWidth*nHeight*4];
format=GL_RGBA;
nBlockSize = 4;
type=GL_UNSIGNED_BYTE;
}else
{
puffer2=new char[nWidth*nHeight*3];
format=GL_RGB;
nBlockSize = 3;
type=GL_UNSIGNED_BYTE;
}
d=0;
int rdiv=0,rmult=0;
for(a=rmask;(a&1)==0;a>>=1)rdiv++;
for(;(a&128)==0;a<<=1)rmult++;
int gdiv=0,gmult=0;
for(a=gmask;(a&1)==0;a>>=1)gdiv++;
for(;(a&128)==0;a<<=1)gmult++;
int bdiv=0,bmult=0;
for(a=bmask;(a&1)==0;a>>=1)bdiv++;
for(;(a&128)==0;a<<=1)bmult++;
int amask=~(rmask & gmask & bmask);
for(a=0;a<(nWidth*nHeight*2);a+=2)
{
c=*(short*)&pixels[a];
r=c&rmask;
g=c&gmask;
b=c&bmask;
r>>=rdiv;
g>>=gdiv;
b>>=bdiv;
r<<=rmult;
g<<=gmult;
b<<=bmult;
if((nBlockSize==4)&&((c&amask)!=0))c=255;else c=0;
puffer2[d]=r;
puffer2[d+1]=g;
puffer2[d+2]=b;
if(nBlockSize==4)puffer2[d+3]=c;
d+=nBlockSize;
}
}
break;
default:
logger.log(" unknown format %d", ddsd.ddpfPixelFormat.dwRGBBitCount);
}
}
if(nBlockSize==-1)
{
logger.log("error unknonw pixelformat %08x", format);
return -1;
}
glGenTextures( 1, &tID );
glBindTexture( GL_TEXTURE_2D, tID );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE );
int nSize;
int nOffset = 0;
if(nNumMipMaps<1)nNumMipMaps=1;
for( int i = 0; i < nNumMipMaps; ++i )
{
if( nWidth == 0 ) nWidth = 1;
if( nHeight == 0 ) nHeight = 1;
if(compressed)nSize = ((nWidth+3)/4) * ((nHeight+3)/4) * nBlockSize;
else nSize=nWidth*nHeight*nBlockSize;
if(!compressed)
{
p=(char*)pixels;
if(puffer2!=0)p=puffer2;
glTexImage2D( GL_TEXTURE_2D, 0, nBlockSize, nWidth, nHeight, 0, format, type, p );
}
else glCompressedTexImage2DARB( GL_TEXTURE_2D, i, format, nWidth, nHeight, 0, nSize, &pixels[nOffset] );
nOffset += nSize;
nWidth = (nWidth / 2);
nHeight = (nHeight / 2);
}
delete[] puffer2;
return tID;
}