//textures.cpp //load textures into OpenGL #include #include #include #include #include #include #include "fileio.h" #include "gamemem.h" #include "textures.h" #include "texturesimport.h" #include "config.h" #include "gametime.h" #include "error.h" #include "screen.h" #include "interfaceutil.h" #include "writeout.h" #include "S3Decompression.h" #define gCanMultiTexture true typedef struct{ void *next; tFileRef tex; } tTextureList; typedef struct{ GLuint ref; GLenum target; } tGLTextureInfo; tTextureList *gTextureList=NULL; int gEnableTextureLoad=true; int gNumTexturesRequested=0; int gNumTexturesLoaded=0; int gTexturesQualityModifier=0; #define kTexturePriorityListFileName "texturepriorities.cfg" //pass raw pixel data to OpenGL void TexturesPassPixelsToGL(tFileRef tex,void *data,GLuint channels,GLuint pixType,GLuint pixSize,int xSize,int ySize,GLenum target,int quality) { int xQual=(quality+1)/3; int yQual=quality/3; if(xQual<0)xQual=0; if(yQual<0)yQual=0; if((xSize>=1024||ySize>=1024)&&(xQual==0||yQual==0)) if(ScreenNoBigTextures()) xQual=yQual=1; //are we using reduced texture quality? if(yQual) { //Calculate size of downsampled texture int newXSize=xSize>>xQual>0?xSize>>xQual:1; int newYSize=ySize>>yQual>0?ySize>>yQual:1; //allocate spce for downsampled texture void *buffer=MemoryAllocateBlock(newXSize*newYSize*4); //create downsample texture gluScaleImage(pixType,xSize,ySize,pixSize,data,newXSize,newYSize,pixSize,buffer); gluBuild2DMipmaps(target,channels,newXSize,newYSize,pixType,pixSize,buffer); MemoryFreeBlock(buffer); } else gluBuild2DMipmaps(target,channels,xSize,ySize,pixType,pixSize,data); } void TexturesLoadImport(tFileRef tex,GLuint target,int quality) { int xSize,ySize; //Get Buffer void *imageBuffer=TexturesLoadImportBuffer(tex,&xSize,&ySize); //TexturesPassPixelsToGL(tex,imageBuffer,GL_COMPRESSED_RGBA_ARB,GL_RGBA,GL_UNSIGNED_BYTE,xSize,ySize,target,quality); TexturesPassPixelsToGL(tex,imageBuffer,GL_RGBA,GL_RGBA,GL_UNSIGNED_BYTE,xSize,ySize,target,quality); MemoryFreeBlock(imageBuffer); } void TexturesPassPixelsToGL3d(tFileRef tex,void *data,GLuint channels,GLuint pixType,GLuint pixSize,int xSize,int ySize,int zSize,GLenum target,int quality) { quality/=3; if(quality<0) quality=0; //are we using reduced texture quality? if(quality) { //Calculate size of downsampled texture int newXSize=xSize>>quality>0?xSize>>quality:1; int newYSize=ySize>>quality>0?ySize>>quality:1; //allocate spce for downsampled texture void *buffer=MemoryAllocateBlock(newXSize*newYSize*zSize*4); //create downsample texture for(int z=0;z> 8)); } void LoadCompressedTexture(tFileRef tex,int quality) { quality/=3; if(quality<0)quality=0; tTextureCacheFile *cache=(tTextureCacheFile*)FileGetDataPtr(tex); tCachedTexture *t0=(tCachedTexture*)(((char*)cache)+EndianS32_BtoN(cache->offsets[0])); if((t0->width>=1024||t0->height>=1024)&&quality==0) if(ScreenNoBigTextures()) quality=1; for(int i=quality;inumEntries);i++) { tCachedTexture *t=(tCachedTexture*)(((char*)cache)+EndianS32_BtoN(cache->offsets[i])); if(EndianS32_BtoN(t->width)&&EndianS32_BtoN(t->height)) if(EndianS32_BtoN(t->compressionSize)) if(ScreenSupportsTextureCompression()) glCompressedTexImage2DARB( EndianS32_BtoN(t->target), EndianS32_BtoN(t->level)-quality, EndianS32_BtoN(t->internalformat), EndianS32_BtoN(t->width), EndianS32_BtoN(t->height), EndianS32_BtoN(t->border), EndianS32_BtoN(t->compressionSize), t->data ); else { UInt16* temp = (UInt16*)t->data; #if TARGET_RT_BIG_ENDIAN for (int i=0;icompressionSize/2;i++) ByteSwap(temp++); #endif void* decompData=MemoryAllocateBlock(sizeof(GLuint)*EndianS32_BtoN(t->width)*EndianS32_BtoN(t->height)); void* decompData2=MemoryAllocateBlock(sizeof(GLuint)*EndianS32_BtoN(t->width)*EndianS32_BtoN(t->height)); DecompressDXT3(EndianS32_BtoN(t->width),EndianS32_BtoN(t->height),(UInt32*)t->data,(UInt32*)decompData); #if TARGET_RT_BIG_ENDIAN for(int y=0;yheight;y++) for(int x=0;xwidth;x++) { UInt32 d=((UInt32*)decompData)[x+(y&1?y-1:y+1)*t->width]; UInt8 b=d>>24; UInt8 g=d>>16; UInt8 r=d>>8; UInt8 a=((UInt32*)decompData)[x+y*t->width]; ((UInt32*)decompData2)[x+y*t->width]=(r<<24)|(g<<16)|(b<<8)|a; } glTexImage2D(EndianS32_BtoN(t->target) ,EndianS32_BtoN(t->level)-quality ,GL_RGBA ,EndianS32_BtoN(t->width) ,EndianS32_BtoN(t->height) ,EndianS32_BtoN(t->border) ,GL_RGBA,GL_UNSIGNED_BYTE,decompData2); #else glTexImage2D(EndianS32_BtoN(t->target) ,EndianS32_BtoN(t->level)-quality ,GL_RGBA ,EndianS32_BtoN(t->width) ,EndianS32_BtoN(t->height) ,EndianS32_BtoN(t->border) ,GL_RGBA,GL_UNSIGNED_BYTE,decompData); #endif MemoryFreeBlock(decompData); MemoryFreeBlock(decompData2); } else glTexImage2D( EndianS32_BtoN(t->target), EndianS32_BtoN(t->level)-quality, EndianS32_BtoN(t->internalformat), EndianS32_BtoN(t->width), EndianS32_BtoN(t->height), EndianS32_BtoN(t->border), EndianS32_BtoN(t->format), EndianS32_BtoN(t->type), t->data ); } } #include "error.h" //load a texture from the file referenced by tex void TexturesLoadFromFile(tFileRef tex,GLenum target) { int quality=gConfig->textureQuality+gTexturesQualityModifier; //if the file type is a raw pixel format, just pass the data to OpenGL char *fileExtension=FileGetExtension(tex); if(!_stricmp(fileExtension,kFileTypeCompressedTexture)){ //precompressed texture LoadCompressedTexture(tex,quality); }else if(!_stricmp(fileExtension,kFileTypeRAW)){ //RAW RGB image if(void *textureData=FileGetDataPtr(tex)){ int size=sqrt(FileGetSize(tex)/3); TexturesPassPixelsToGL(tex,textureData,GL_RGB,GL_RGB,GL_UNSIGNED_BYTE,size,size,target,quality); } }else if(!_stricmp(fileExtension,kFileTypeRAW3d)){ //RAW 3D RGBA image if(void *textureData=FileGetDataPtr(tex)){ int size=sqrt(FileGetSize(tex)/8); if(ScreenSupports3DTextures()) TexturesPassPixelsToGL3d(tex,textureData,GL_RGBA,GL_RGBA,GL_UNSIGNED_BYTE,size,size,2,target,quality); else TexturesPassPixelsToGL(tex,textureData,GL_RGBA,GL_RGBA,GL_UNSIGNED_BYTE,size,size,target,quality); } }else if(!_stricmp(fileExtension,kFileTypeGrayscaleRAW)){ //RAW grayscale image if(void *textureData=FileGetDataPtr(tex)){ int size=sqrt(FileGetSize(tex)); TexturesPassPixelsToGL(tex,textureData,1,GL_LUMINANCE,GL_UNSIGNED_BYTE,size,size,target,quality); } }else if(!_stricmp(fileExtension,".RGBA")){ //RAW RGBA image if(void *textureData=FileGetDataPtr(tex)){ int size=sqrt(FileGetSize(tex)/4); TexturesPassPixelsToGL(tex,textureData,GL_RGBA,GL_RGBA,GL_UNSIGNED_BYTE,size,size,target,quality); } } //otherwise decompress image data else TexturesLoadImport(tex,target,quality); //other image formats } int TexturesSelectTextureUnit(int unit) { GLint numTextureUnits; glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&numTextureUnits); if(unittarget=GL_TEXTURE_2D; char *fileExtension=FileGetExtension(tex); if(fileExtension) if(!_stricmp(fileExtension,kFileTypeRAW3d)) if(ScreenSupports3DTextures()) info->target=GL_TEXTURE_3D; glGenTextures(1,&info->ref); glBindTexture(info->target,info->ref); //glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE,GL_TRUE); //glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_SHARED_APPLE); TexturesLoadFromFile(tex,info->target); glTexParameteri(info->target,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(info->target,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(info->target,GL_TEXTURE_MIN_FILTER,gConfig->textureFilter?GL_LINEAR_MIPMAP_LINEAR:GL_LINEAR_MIPMAP_NEAREST); if(gConfig->textureFilter==2) glTexParameterf(info->target,GL_TEXTURE_MAX_ANISOTROPY_EXT,10); tTextureList *textureList=gTextureList; gTextureList=(tTextureList*)MemoryAllocateBlock(sizeof(tTextureList)); gTextureList->next=(void*)textureList; gTextureList->tex=tex; gNumTexturesLoaded++; gFileTable[tex].parsedData=(void*)info; gFileTable[tex].parsed=true; } void TexturesUnloadAll() { while(gTextureList!=NULL) { tTextureList *next=(tTextureList*)gTextureList->next; glDeleteTextures(1,&((tGLTextureInfo*)(gFileTable[gTextureList->tex].parsedData))->ref); MemoryFreeBlock(gFileTable[gTextureList->tex].parsedData); gFileTable[gTextureList->tex].parsed=false; FileReleaseData(gTextureList->tex); MemoryFreeBlock(gTextureList); gTextureList=next; } } //Selects the texture in the file referenced to by tex void TexturesSelectTex(tFileRef tex) { if(tex==kFileErr) tex=FileGetReference("null.raw"); //is the texture loaded? if(!gFileTable[tex].parsed) TexturesLoadTex(tex); if(gFileTable[tex].parsed){ if(((tGLTextureInfo*)gFileTable[tex].parsedData)->target==GL_TEXTURE_3D) { glDisable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_3D); } else{ glEnable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_3D); } // GLboolean b; // if(!glAreTexturesResident(1,(GLuint*)gFileTable[tex].parsedData,&b)) // SysBeep(0); glBindTexture(((tGLTextureInfo*)gFileTable[tex].parsedData)->target,((tGLTextureInfo*)gFileTable[tex].parsedData)->ref); } }