63#include <srSurfaceIOManager.hpp>
64#include <srExtension.hpp>
66#include <srBinIStream.hpp>
67#include <srColorSurface.hpp>
68#include <srTextureIFace.hpp>
77#define FILE_HEADER_NAME "Texture File Cache Header"
80char *TextureFileCache::_FileNamePtr =
NULL;
81static int Instances=0;
88static char* Get_Compression_Buffer(
int size)
92 return &(compression_buffer[0]);
95static void Verify_Compression_Buffer()
107 const unsigned char * in,
110 unsigned int * out_len
113 static int Decompress
115 const unsigned char * in,
118 unsigned int * out_len
123int Compressor::Compress(
const unsigned char * in,
unsigned int in_len,
124 unsigned char * out,
unsigned int * out_len )
126 if (!in || !out || !out_len)
132 memcpy(out, in, in_len);
139int Compressor::Decompress(
const unsigned char * in,
unsigned int in_len,
140 unsigned char * out,
unsigned int * out_len )
142 if (!in || !out || !out_len)
148 memcpy(out, in, in_len);
173TextureFileCache::TextureFileCache(
const char *fileprefix):
174 File(_Create_File_Name(fileprefix)),
175 CurrentTexture(
NULL),
189 memset(CachedSurfaces, 0,
sizeof(CachedSurfaces));
194 FileHeader fileheader;
197 handle->
Read(&fileheader,
sizeof(fileheader));
199 if (fileheader.Version != FileHeader::TCF_VERSION) {
227char *TextureFileCache::_Create_File_Name(
const char *fileprefix)
229 bool addpath = (*fileprefix !=
'\\' && fileprefix[1] !=
':');
231 assert(!_FileNamePtr);
232 _FileNamePtr =
W3DNEWARRAY char[strlen(fileprefix) + (addpath ? 256 : 6)];
234 char path[_MAX_PATH];
235 if (addpath && _getcwd(path, _MAX_PATH )) {
236 sprintf(_FileNamePtr,
"%s\\%s.tfc", path, fileprefix);
239 strcpy(_FileNamePtr, fileprefix);
240 strcat(_FileNamePtr,
".tfc");
244 return(_FileNamePtr);
260TextureFileCache::~TextureFileCache()
263 Close_Texture_Handle();
282void TextureFileCache::Reset_File()
288 FileHeader fileheader;
289 fileheader.Version = FileHeader::TCF_VERSION;
292 handle->
Write(&fileheader,
sizeof(fileheader));
316bool TextureFileCache::Save_Texture(
const char *texturename, srTextureIFace::MultiRequest& mreq, srColorSurfaceIFace& origsurface)
323 Open_Texture_Handle(texturename);
326 TextureHandle =
File.Create_Tag(texturename);
327 if (!TextureHandle) {
328 Close_Texture_Handle();
337 Header.NumMipMaps = (mreq.smallLOD - mreq.largeLOD) + 1;
338 Header.LargestWidth = mreq.levels[mreq.largeLOD]->getWidth();
339 Header.LargestHeight = mreq.levels[mreq.largeLOD]->getHeight();
340 Header.SourceWidth = origsurface.getWidth();
341 Header.SourceHeight = origsurface.getHeight();
342 mreq.levels[mreq.largeLOD]->getPixelFormat(Header.PixelFormat);
343 origsurface.getPixelFormat(Header.SourcePixelFormat);
349 TextureHandle->Write(&Header,
sizeof(Header));
352 Offsets =
W3DNEWARRAY OffsetTableType[Header.NumMipMaps + 1];
355 int tableoffset = TextureHandle->Tell();
356 TextureHandle->Write(Offsets,
sizeof(OffsetTableType) * (Header.NumMipMaps + 1));
359 for (idx = 0, lod = mreq.largeLOD; lod <= mreq.smallLOD; idx++, lod++) {
360 srColorSurface *surface = mreq.levels[lod];
363 Offsets[idx].Offset = TextureHandle->Tell();
364 Offsets[idx].Size = surface->getDataSize();
367 Add_Cached_Surface(surface);
369 int compsize,retcode;
371 int buf_size=surface->getDataSize();
372 retcode = Compressor::Compress( (
const unsigned char *) surface->getDataPtr(),
373 (
unsigned int) surface->getDataSize(),
374 (
unsigned char *) Get_Compression_Buffer(buf_size),
375 (
unsigned *) &compsize);
379 assert(retcode ==
TRUE);
380 Verify_Compression_Buffer();
382 int readin = TextureHandle->Write(Get_Compression_Buffer(compsize), compsize);
383 assert(readin == compsize);
386 int pos = TextureHandle->Seek(0,
SEEK_END);
389 Offsets[idx].Offset = TextureHandle->Tell();
390 Offsets[idx].Size = 0;
393 TextureHandle->Seek(tableoffset,
SEEK_SET);
394 TextureHandle->Write(Offsets,
sizeof(OffsetTableType) * (Header.NumMipMaps + 1));
396 pos = TextureHandle->Seek(0,
SEEK_END);
399 TextureHandle->End_Write_Access();
417srColorSurfaceIFace *TextureFileCache::Load_Original_Texture_Surface(
const char *texturename)
420 if (Open_Texture_Handle(texturename)) {
422 srColorSurfaceIFace *surface =
W3DNEW srColorSurface(Header.SourcePixelFormat, Header.SourceWidth, Header.SourceHeight);
440srColorSurfaceIFace *TextureFileCache::Get_Surface(
const char *texturename,
unsigned int reduce_factor)
445 if (!Open_Texture_Handle(texturename)) {
449 if (reduce_factor >= (
unsigned int)(Header.NumMipMaps)) {
450 reduce_factor=Header.NumMipMaps-1;
454 int width = Header.LargestWidth >> reduce_factor;
455 int height = Header.LargestHeight >> reduce_factor;
456 if (!width) width = 1;
457 if (!height) height = 1;
460 srColorSurface *surface =
W3DNEW srColorSurface(Header.PixelFormat, width, height);
461 int size = Texture_Size(reduce_factor);
462 assert(size == surface->getDataSize());
465 srColorSurface *cached = Find_Cached_Surface(size);
467 assert(size == cached->getDataSize());
468 memcpy(surface->getDataPtr(), cached->getDataPtr(), size);
472 Add_Cached_Surface(surface);
475 Read_Texture(reduce_factor, surface);
494bool TextureFileCache::Load_Texture(
const char *texturename, srTextureIFace::MultiRequest& mreq)
498 if (!Open_Texture_Handle(texturename)) {
511 int idxsize = Texture_Size(0);
515 for (lod = mreq.largeLOD; lod <= mreq.smallLOD; lod++) {
516 lodsize = mreq.levels[lod]->getDataSize();
517 if (lodsize <= idxsize) {
522 assert(lodsize != -1);
525 for (idx = 0; idx < Header.NumMipMaps; idx++) {
526 idxsize = Texture_Size(idx);
527 if (idxsize <= lodsize) {
533 unsigned firstlod = lod;
536 if (idxsize == lodsize) {
538 while ((lod <= mreq.smallLOD) && (idx < Header.NumMipMaps)) {
539 srColorSurface *surface = mreq.levels[lod];
540 int size = surface->getDataSize(); assert(Texture_Size(idx) == size);
543 srColorSurface *cached = Find_Cached_Surface(size);
547 assert(size == cached->getDataSize());
550 memcpy(surface->getDataPtr(), cached->getDataPtr(), size);
554 Add_Cached_Surface(surface);
557 Read_Texture(idx, surface);
565 unsigned lastlod = lod - 1;
568 srColorSurfaceIFace *surface =
NULL;
569 if (firstlod < lastlod) {
570 surface = mreq.levels[firstlod];
571 surface->addReference();
578 if (mreq.largeLOD < firstlod) {
581 surface = Create_First_Texture_As_Surface(mreq.levels[mreq.largeLOD]);
585 for (lod = mreq.largeLOD; lod <= firstlod; lod++) {
587 surface->copy(*mreq.levels[lod]);
592 if (lastlod < mreq.smallLOD) {
595 surface = Create_First_Texture_As_Surface(mreq.levels[mreq.largeLOD]);
599 for (lod = lastlod + 1; lod <= mreq.smallLOD; lod++) {
601 surface->copy(*mreq.levels[lod]);
626void TextureFileCache::Read_Texture(
int offsetidx, srColorSurface *surface)
629 TextureHandle->Seek(Offsets[offsetidx].Offset,
SEEK_SET);
632 int compsize = Compressed_Texture_Size(offsetidx);
635 int readin = TextureHandle->Read(Get_Compression_Buffer(compsize), compsize);
636 assert(readin == compsize);
639 Verify_Compression_Buffer();
642 int retcode, decompsize;
643 retcode = Compressor::Decompress( (
const unsigned char*) Get_Compression_Buffer(compsize),
644 (
unsigned int) compsize,
645 (
unsigned char*) surface->getDataPtr(),
646 (
unsigned *) &decompsize);
649 assert(retcode ==
TRUE);
650 assert(decompsize == Texture_Size(offsetidx));
651 Verify_Compression_Buffer();
667srColorSurfaceIFace *TextureFileCache::Create_First_Texture_As_Surface(srColorSurfaceIFace *surfacetype)
669 srColorSurfaceIFace::PixelFormat pf;
672 surfacetype->getPixelFormat(pf);
675 srColorSurface *surface =
W3DNEW srColorSurface(pf, Header.LargestWidth, Header.LargestHeight);
676 assert(Texture_Size(0) == surface->getDataSize());
679 Read_Texture(0, surface);
696bool TextureFileCache::Open_Texture_Handle(
const char *fname)
699 assert(CurrentTexture);
700 if (!strcmpi(fname, CurrentTexture)) {
704 Close_Texture_Handle();
706 if (!CurrentTexture) {
707 CurrentTexture = strdup(fname);
723 TextureHandle =
File.Open_Tag(fname);
726 TextureHandle->Read(&Header,
sizeof(Header));
734 delete TextureHandle;
735 TextureHandle =
NULL;
742 Offsets =
W3DNEWARRAY OffsetTableType[Header.NumMipMaps + 1];
743 TextureHandle->Read(Offsets,
sizeof(OffsetTableType) * (Header.NumMipMaps + 1));
763void TextureFileCache::Close_Texture_Handle()
765 if (CurrentTexture) {
766 free(CurrentTexture);
767 CurrentTexture =
NULL;
770 delete TextureHandle;
771 TextureHandle =
NULL;
773 while (NumCachedTextures--) {
774 assert(CachedSurfaces[NumCachedTextures]);
775 CachedSurfaces[NumCachedTextures]->release();
776 CachedSurfaces[NumCachedTextures] = 0;
778 NumCachedTextures = 0;
785 assert(!CurrentTexture);
801srColorSurface *TextureFileCache::Find_Cached_Surface(
int size)
804 for (
int idx = 0; idx < NumCachedTextures; idx++) {
805 if (CachedSurfaces[idx]->getDataSize() == size) {
806 return(CachedSurfaces[idx]);
824void TextureFileCache::Add_Cached_Surface(srColorSurface *surface)
827 assert(!Find_Cached_Surface(surface->getDataSize()));
830 int surface_idx = -1;
831 if (NumCachedTextures == MAX_CACHED_SURFACES) {
834 int smallsize = 0xfffffff;
838 for (
int idx = 0; idx < NumCachedTextures; idx++) {
839 int size = CachedSurfaces[idx]->getDataSize();
840 if (size < smallsize) {
846 surface_idx = smallidx;
847 CachedSurfaces[idx]->release();
848 CachedSurfaces[idx] = 0;
851 assert(NumCachedTextures < MAX_CACHED_SURFACES);
852 surface_idx = NumCachedTextures;
855 assert(surface_idx >= 0);
856 assert(!CachedSurfaces[surface_idx]);
858 CachedSurfaces[surface_idx] = surface;
859 surface->addReference();
863bool TextureFileCache::Validate_Texture(
const char* FileName)
867 if (!Texture_Exists(FileName)) {
868 if (!TextureLoader::Texture_File_Exists(FileName)) {
872 srColorSurfaceIFace* TempSurfacePtr = ::Load_Surface(FileName);
873 if (!TempSurfacePtr)
return false;
875 int w=TempSurfacePtr->getWidth();
876 srColorSurfaceIFace::PixelFormat pf;
877 TempSurfacePtr->getPixelFormat(pf);
879 srTextureIFace::MultiRequest mr;
880 for (
int cnt=0;cnt<srTextureIFace::MAX_LOD;++cnt) mr.levels[cnt]=0;
881 for (cnt=0;cnt<srTextureIFace::MAX_LOD;) {
882 mr.levels[cnt]=
W3DNEW srColorSurface(pf,w,w);
883 mr.levels[cnt]->copy(*TempSurfacePtr);
891 TempSurfacePtr->release();
893 for (cnt=0;cnt<srTextureIFace::MAX_LOD;++cnt) {
894 if (mr.levels[cnt]) mr.levels[cnt]->release();
900int TextureFileCache::Texture_Exists(
const char *fname)
903 return(
File.Does_Tag_Exist(fname));
virtual unsigned long Get_Date_Time(void)
virtual int Open(char const *filename, int rights=READ)=0
virtual bool Uninitialised_Grow(int newsize)
int Read(void *buf, int nbytes)
int Write(const void *buf, int nbytes)
FileFactoryClass * _TheFileFactory
#define BUFFER_OVERRUN_TEST_VALUE
void Save_Texture(TextureClass *texture, ChunkSaveClass &csave)