Generating texture names on startup

This commit is contained in:
Jens Hemprich 2006-09-03 19:49:40 +00:00
parent 717a5bd03c
commit 3b6147c73f
3 changed files with 187 additions and 74 deletions

View File

@ -16,7 +16,9 @@
TexDB::Record* TexDB::Record::s_FreeRecords = NULL; TexDB::Record* TexDB::Record::s_FreeRecords = NULL;
TexDB::RecordArray* TexDB::Record::s_RecordArrays = NULL; TexDB::RecordArray* TexDB::Record::s_RecordArrays = NULL;
TexDB::SubRecord* TexDB::SubRecord::s_FreeSubRecords = NULL; TexDB::SubRecord* TexDB::SubRecord::s_FreeSubRecords = NULL;
TexDB::SubRecordArray* TexDB::SubRecord::s_SubRecordArrays = NULL;
int TexDB::RecordArraySize = 16; int TexDB::RecordArraySize = 16;
int TexDB::textureNamesCount = 1;
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Construction/Destruction // Construction/Destruction
@ -36,20 +38,34 @@ TexDB::TexDB(unsigned int MemorySize)
m_texmem_2_record = static_cast<Record**>(AllocBuffer(MemorySize >> 3, sizeof(Record*))); m_texmem_2_record = static_cast<Record**>(AllocBuffer(MemorySize >> 3, sizeof(Record*)));
memset(m_texmem_2_record, 0, (MemorySize >> 3) * sizeof(Record*)); memset(m_texmem_2_record, 0, (MemorySize >> 3) * sizeof(Record*));
#endif #endif
// Prealloc Reocrds proportional to the amount of tex memory // Prealloc records proportional to the amount of tex memory
RecordArraySize = MemorySize / (1024 * 1024) * 256; // preallocate 256 records per mb RecordArraySize = MemorySize / (1024 * 1024) * 256; // preallocate 256 records per mb
// Number of texture names to be allocaed by default (See GL_PALETTE_EXT path in PGTexture::MakeReady)
// This may allocate more texture names than needed if the condition is true
textureNamesCount = OpenGL.ColorAlphaUnit2 == 0
&& OpenGL.FogTextureUnit >= GL_TEXTURE1_ARB
&& InternalConfig.EXT_paletted_texture
? 2 : 1;
// Prealloc some texdb records to avoid out of memory problems later // Prealloc some texdb records to avoid out of memory problems later
TexDB::Record::Init(); TexDB::Record::Init();
if (InternalConfig.GenerateSubTextures)
{
TexDB::SubRecord::Init();
}
} }
TexDB::~TexDB( void ) TexDB::~TexDB( void )
{ {
Clear(); Clear();
delete[] m_first; delete[] m_first;
TexDB::SubRecord::Cleanup();
#ifdef OPTIMISE_TEXTURE_LOOKUP #ifdef OPTIMISE_TEXTURE_LOOKUP
if (m_texmem_2_record) FreeBuffer(m_texmem_2_record); if (m_texmem_2_record) FreeBuffer(m_texmem_2_record);
#endif #endif
if (InternalConfig.GenerateSubTextures)
{
TexDB::SubRecord::Cleanup();
}
TexDB::Record::Cleanup();
} }
TexDB::Record* TexDB::Find(FxU32 startAddress, const GrTexInfo *info, FxU32 hash, bool *pal_change, SubTexCoord_t* subtexcoords) const TexDB::Record* TexDB::Find(FxU32 startAddress, const GrTexInfo *info, FxU32 hash, bool *pal_change, SubTexCoord_t* subtexcoords) const
@ -320,6 +336,19 @@ void TexDB::Clear( void )
} }
} }
// Must be called right after the OpenGL context has been built
void TexDB::initOpenGL(void)
{
Record::initOpenGL();
}
// Must be called before destroying the OpenGL context
void TexDB::cleanupOpenGL(void)
{
Clear();
Record::cleanupOpenGL();
}
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
// TexDB::Record Class implementation // TexDB::Record Class implementation
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
@ -347,6 +376,49 @@ void TexDB::Record::Cleanup()
return; return;
} }
// Init free chunks with OpenGL stuff
void TexDB::Record::initOpenGL(void)
{
glReportErrors("TexDB::Record::initOpenGL");
RecordArray* ra = s_RecordArrays;
// Only the first chunk of free records is initialised,
// so this has to be called each time new records have been allocated
if (ra)
{
const GLfloat one = 1.0f;
for(int i = 0; i < RecordArraySize; i++)
{
// Pre-generate texture names (unused when using subtextures)
GLuint* num = &s_RecordArrays->records[i].texNum;
glGenTextures(TexDB::textureNamesCount, &num[0]);
glPrioritizeTextures(TexDB::textureNamesCount, &num[0], &one);
glReportError();
}
}
return;
}
void TexDB::Record::cleanupOpenGL(void)
{
glReportErrors("TexDB::Record::cleanupOpenGL");
RecordArray* ra = s_RecordArrays;
while (ra)
{
// Delete pre-generated texture names
for(int i = 0; i < RecordArraySize; i++)
{
glDeleteTextures(textureNamesCount, &ra->records[i].texNum);
glReportError();
ra->records[i].texNum =
ra->records[i].tex2Num = 0;
}
ra = ra->next;
}
return;
}
void TexDB::Record::AllocRecords() void TexDB::Record::AllocRecords()
{ {
#ifdef OGL_UTEX_MEM #ifdef OGL_UTEX_MEM
@ -368,6 +440,7 @@ void* TexDB::Record::operator new(size_t s)
if (s_FreeRecords == NULL) if (s_FreeRecords == NULL)
{ {
AllocRecords(); AllocRecords();
initOpenGL();
} }
p = s_FreeRecords; p = s_FreeRecords;
s_FreeRecords = p->next; s_FreeRecords = p->next;
@ -388,34 +461,11 @@ void TexDB::Record::operator delete(void* p)
TexDB::Record::Record(TexDB::TextureMode texturemode) TexDB::Record::Record(TexDB::TextureMode texturemode)
{ {
if (texturemode <= Two)
{
GLfloat one;
glGenTextures(1, &texNum);
glPrioritizeTextures(1, &texNum, &one);
if (texturemode == TexDB::Two )
{
glGenTextures(1, &tex2Num);
glPrioritizeTextures(1, &tex2Num, &one);
}
else
{
tex2Num = 0;
}
}
} }
TexDB::Record::~Record(void) TexDB::Record::~Record(void)
{ {
if (subrecords == NULL) if (subrecords)
{
glDeleteTextures(1, &texNum);
if (tex2Num != 0)
{
glDeleteTextures(1, &tex2Num);
}
}
else
{ {
SubRecord* next = this->subrecords; SubRecord* next = this->subrecords;
for (SubRecord* s = next; next != NULL; s = next) for (SubRecord* s = next; next != NULL; s = next)
@ -458,25 +508,83 @@ void TexDB::Record::WipeInside(const SubTexCoord_t* subtexcoords)
// TexDB::SubRecord Class implementation // TexDB::SubRecord Class implementation
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
TexDB::SubRecord::SubRecord(TexDB::TextureMode texturemode) void TexDB::SubRecord::Init()
{ {
glGenTextures(1, &texNum); // Alloc a couple of subrecords in advance
if (texturemode == TexDB::SubTextureTwo) AllocSubRecords();
{
glGenTextures(1, &tex2Num);
}
else
{
tex2Num = 0;
}
} }
TexDB::SubRecord::~SubRecord( void ) void TexDB::SubRecord::Cleanup()
{ {
glDeleteTextures(1, &texNum); SubRecordArray* sra = s_SubRecordArrays;
if (tex2Num != 0) while (sra)
{ {
glDeleteTextures(1, &tex2Num); SubRecordArray* next = sra->next;
FreeObject(sra);
#ifdef OGL_UTEX_MEM
GlideMsg("Freed TexDB subrecord array at 0x%x\n", sra);
#endif
sra = next;
}
s_SubRecordArrays = NULL;
s_FreeSubRecords = NULL;
return;
}
void TexDB::SubRecord::initOpenGL()
{
glReportErrors("TexDB::SubRecord::initOpenGL");
SubRecordArray* sra = s_SubRecordArrays;
// Only the first chunk of free records is initialised,
// so this has to be called each time new records have been allocated
if (sra)
{
const GLfloat one = 1.0f;
for(int i = 0; i < RecordArraySize; i++)
{
// Pre-generate texture names (unused when using subtextures)
GLuint* num = &s_SubRecordArrays->subrecords[i].texNum;
glGenTextures(TexDB::textureNamesCount, num);
glPrioritizeTextures(TexDB::textureNamesCount, num, &one);
glReportError();
}
}
return;
}
void TexDB::SubRecord::cleanupOpenGL()
{
glReportErrors("TexDB::SubRecord::cleanupOpenGL");
SubRecordArray* sra = s_SubRecordArrays;
while (sra)
{
// Delete pre-generated texture names
for(int i = 0; i < RecordArraySize; i++)
{
glDeleteTextures(textureNamesCount, &sra->subrecords[i].texNum);
glReportError();
sra->subrecords[i].texNum =
sra->subrecords[i].tex2Num = 0;
}
sra = sra->next;
}
return;
}
void TexDB::SubRecord::AllocSubRecords()
{
#ifdef OGL_UTEX_MEM
GlideMsg("Allocating TexDB record array with %d entries\n", RecordArraySize);
#endif
SubRecordArray* next = s_SubRecordArrays ? s_SubRecordArrays->next : NULL;
s_SubRecordArrays = static_cast<SubRecordArray*>(AllocObject(sizeof(SubRecordArray) + (RecordArraySize -1) * sizeof(SubRecord)));
s_SubRecordArrays->next = next;
for(int i = 0; i < RecordArraySize; i++)
{
s_SubRecordArrays->subrecords[i].next = s_FreeSubRecords;
s_FreeSubRecords = &s_SubRecordArrays->subrecords[i];
} }
} }
@ -485,45 +593,30 @@ void* TexDB::SubRecord::operator new(size_t s)
SubRecord* p; SubRecord* p;
if (s_FreeSubRecords == NULL) if (s_FreeSubRecords == NULL)
{ {
p = reinterpret_cast<SubRecord*>(NewPtrSys(s)); AllocSubRecords();
#ifdef OGL_UTEX_MEM initOpenGL();
GlideMsg("Allocated TexDB subrecord at 0x%x\n", p);
#endif
} }
else p = s_FreeSubRecords;
{ s_FreeSubRecords = p->next;
p = s_FreeSubRecords;
s_FreeSubRecords = p->next;
#ifdef OGL_UTEX_MEM #ifdef OGL_UTEX_MEM
GlideMsg("Using TexDB subrecord at 0x%x\n", p); GlideMsg("Using TexDB subrecord at 0x%x\n", p);
#endif #endif
}
return p; return p;
} }
void TexDB::SubRecord::operator delete(void* p) void TexDB::SubRecord::operator delete(void* p)
{ {
#ifdef OGL_UTEX_MEM #ifdef OGL_UTEX_MEM
GlideMsg("Moving TexDB subrecord at 0x%x to free-list\n", p); GlideMsg("Moving TexDB subrecord at 0x%x to free list\n", p);
#endif #endif
// reinterpret_cast<TexDB::SubRecord*>(p)->next = s_FreeSubRecords; reinterpret_cast<TexDB::SubRecord*>(p)->next = s_FreeSubRecords;
SubRecord* s = reinterpret_cast<TexDB::SubRecord*>(p); s_FreeSubRecords = reinterpret_cast<TexDB::SubRecord*>(p);
s->next = s_FreeSubRecords;
s_FreeSubRecords = s;
} }
void TexDB::SubRecord::Cleanup() TexDB::SubRecord::SubRecord(TexDB::TextureMode texturemode)
{
}
TexDB::SubRecord::~SubRecord( void )
{ {
SubRecord* s = s_FreeSubRecords;
while (s)
{
#ifdef OGL_UTEX_MEM
GlideMsg("Deleting TexDB subrecord at 0x%x\n", s);
#endif
SubRecord* next = s->next;
DisposePtr(reinterpret_cast<Ptr>(s));
s = next;
}
s_FreeSubRecords = NULL;
return;
} }

View File

@ -30,7 +30,6 @@
class TexDB class TexDB
{ {
public: public:
void Clear( void );
enum TextureMode enum TextureMode
{ {
One = 0, One = 0,
@ -38,8 +37,14 @@ public:
SubTextureOne = 2, SubTextureOne = 2,
SubTextureTwo = 3 SubTextureTwo = 3
}; };
struct SubRecordArray;
struct SubRecord struct SubRecord
{ {
protected:
static SubRecord* s_FreeSubRecords;
static SubRecordArray* s_SubRecordArrays;
static void AllocSubRecords();
public: public:
SubRecord *next; SubRecord *next;
public: public:
@ -67,12 +72,19 @@ public:
}; };
void* operator new(size_t s); void* operator new(size_t s);
void operator delete(void* p); void operator delete(void* p);
static void Init();
static void Cleanup(); static void Cleanup();
static SubRecord* s_FreeSubRecords; static void initOpenGL();
static void cleanupOpenGL();
private: private:
void* operator new[](size_t s); // not used so we don't need an implementation void* operator new[](size_t s); // not used so we don't need an implementation
void operator delete[](void* p); void operator delete[](void* p);
}; };
struct SubRecordArray
{
SubRecordArray* next;
SubRecord subrecords[1];
};
struct RecordArray; struct RecordArray;
class Record class Record
@ -111,21 +123,28 @@ public:
void operator delete(void* p); void operator delete(void* p);
static void Init(); static void Init();
static void Cleanup(); static void Cleanup();
static void initOpenGL();
static void cleanupOpenGL();
private: private:
void* operator new[](size_t s); // not used so we don't need an implementation void* operator new[](size_t s); // not used so we don't need an implementation
void operator delete[](void* p); // not used so we don't need an implementation void operator delete[](void* p); // not used so we don't need an implementation
}; };
static int RecordArraySize;
struct RecordArray struct RecordArray
{ {
RecordArray* next; RecordArray* next;
Record records[1]; Record records[1];
}; };
TexDB(unsigned int MemorySize);
virtual ~TexDB(void);
void Clear(void);
void initOpenGL();
void cleanupOpenGL();
Record* Add(FxU32 startAddress, FxU32 endAddress, const GrTexInfo *info, FxU32 hash, TexDB::TextureMode texturemode, const SubTexCoord_t* subtexcoords); Record* Add(FxU32 startAddress, FxU32 endAddress, const GrTexInfo *info, FxU32 hash, TexDB::TextureMode texturemode, const SubTexCoord_t* subtexcoords);
Record* Find(FxU32 startAddress, const GrTexInfo *info, FxU32 hash, bool *pal_change, SubTexCoord_t* subtexcoords) const; Record* Find(FxU32 startAddress, const GrTexInfo *info, FxU32 hash, bool *pal_change, SubTexCoord_t* subtexcoords) const;
void WipeRange(FxU32 startAddress, FxU32 endAddress, FxU32 hash); void WipeRange(FxU32 startAddress, FxU32 endAddress, FxU32 hash);
TexDB(unsigned int MemorySize); static int RecordArraySize;
virtual ~TexDB(void); protected:
static int textureNamesCount;
private: private:
unsigned int numberOfTexSections; unsigned int numberOfTexSections;
Record** m_first; Record** m_first;

View File

@ -296,6 +296,7 @@ grSstWinOpen(FxU32 hwnd,
// Initialise the frame buffer emulation // Initialise the frame buffer emulation
RenderInitialize(); RenderInitialize();
s_Framebuffer.initialise(&Glide.FrameBuffer, &Glide.TempBuffer); s_Framebuffer.initialise(&Glide.FrameBuffer, &Glide.TempBuffer);
Textures->initOpenGL();
#ifdef OGL_DONE #ifdef OGL_DONE
GlideMsg( "----Start of grSstWinOpen()\n" ); GlideMsg( "----Start of grSstWinOpen()\n" );
@ -543,7 +544,7 @@ grSstWinClose( void )
#endif #endif
} }
Textures->Clear(); Textures->cleanupOpenGL();
GLExtensionsCleanup(); GLExtensionsCleanup();
RenderFree(); RenderFree();
FinaliseOpenGLWindow(); FinaliseOpenGLWindow();