diff --git a/projects/mtg/include/WCachedResource.h b/projects/mtg/include/WCachedResource.h index 6063f05c4..472c42d45 100644 --- a/projects/mtg/include/WCachedResource.h +++ b/projects/mtg/include/WCachedResource.h @@ -18,24 +18,47 @@ public: virtual void Nullify()=0; //For when our size is 0, so we don't free anything by mistake. virtual unsigned long size()=0; //Size of cached item in bytes. - virtual void Refresh(string filename)=0; //Basically calls Attempt(filename) and remaps in situ. virtual bool isGood()=0; //Return true if this has data. - virtual bool Attempt(string filename, int submode, int & error)=0; //Returns true if we've loaded our data and isGood(). + virtual bool isLocked(); //Is the resource locked? + virtual void lock(); //Lock it. + virtual void unlock(bool force = false); //Unlock it. Forcing a lock will also remove "permanent" status. -protected: - bool isLocked(); //Is the resource locked? bool isPermanent(); //Is the resource permanent? - void lock(); //Lock it. void deadbolt(); //Make it permanent. - void unlock(bool force = false); //Unlock it. Forcing a lock will also remove "permanent" status. void hit(); //Update resource's last used time. +protected: int loadedMode; //What submode settings were we loaded with? (For refresh) unsigned int lastTime; //When was the last time we were hit? unsigned char locks; //Remember to unlock when we're done using locked stuff, or else this'll be useless. }; -class WCachedTexture: public WResource{ +class WCachedResource: public WResource { +public: + friend class WResourceManager; + template friend class WCache; + + virtual void Refresh(string filename)=0; //Basically calls Attempt(filename) and remaps in situ. + virtual bool Attempt(string filename, int submode, int & error)=0; //Returns true if we've loaded our data and isGood(). +}; + + +class WTrackedQuad: public WResource { +public: + WTrackedQuad(string _resname); + ~WTrackedQuad(); + void Nullify(); + unsigned long size(); + bool isGood(); + + string resname; + JQuad * quad; +#ifdef DEBUG_CACHE + static int totalTracked; +#endif +}; + +class WCachedTexture: public WCachedResource{ public: friend class WResourceManager; template friend class WCache; @@ -44,23 +67,28 @@ public: void Refresh(string filename); unsigned long size(); - bool isGood(); + bool isGood(); + bool isLocked(); bool Attempt(string filename, int submode, int & error); bool compare(JTexture * t) {return (t == texture);}; void Nullify(); JTexture * Actual(); //Return this texture as is. Does not make a new one. JQuad * GetQuad(string resname); - JQuad * GetQuad(float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f,string resname=""); //Get us a new/existing quad. + + WTrackedQuad* GetTrackedQuad(float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f,string resname=""); //Get us a new/existing quad. + + JQuad * GetQuad(float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f,string resname=""); //Alias to GetTrackedQuad. JQuad * GetCard(float offX=0.0f, float offY=0.0f, float width=0.0f, float height=0.0f,string resname=""); //Same as above, but centered when new. + bool ReleaseQuad(JQuad* quad); //We're done with this quad, so delete and stop tracking. True if existed. protected: JTexture * texture; bool bVRAM; - map trackedQuads; + vector trackedQuads; }; -class WCachedParticles: public WResource{ +class WCachedParticles: public WCachedResource{ public: friend class WResourceManager; template friend class WCache; @@ -79,7 +107,7 @@ protected: hgeParticleSystemInfo * particles; }; -class WCachedSample: public WResource{ +class WCachedSample: public WCachedResource{ public: friend class WResourceManager; template friend class WCache; diff --git a/projects/mtg/include/WResourceManager.h b/projects/mtg/include/WResourceManager.h index 580d05f96..dd0f815db 100644 --- a/projects/mtg/include/WResourceManager.h +++ b/projects/mtg/include/WResourceManager.h @@ -23,8 +23,8 @@ enum ENUM_WRES_INFO{ enum ENUM_RETRIEVE_STYLE{ RETRIEVE_EXISTING, //Only returns a resource if it already exists. Does not lock or unlock. RETRIEVE_NORMAL, //Returns or creates a resource. Does not change lock status. - RETRIEVE_LOCK, //As above, locks cached resource. Not for quads. - RETRIEVE_UNLOCK, //As above, unlocks cached resource. Not for quads. + RETRIEVE_LOCK, //As above, locks cached resource. + RETRIEVE_UNLOCK, //As above, unlocks cached resource. RETRIEVE_RESOURCE, //Only retrieves a managed resource. Does not make a new one. RETRIEVE_VRAM, //Retrieve it, and use vram if have to we create it. Must still remove it. RETRIEVE_MANAGE, //Makes resource permanent. @@ -104,7 +104,9 @@ protected: #endif }; -struct WManagedQuad { +class WManagedQuad { +public: + WManagedQuad() {texture = NULL;}; WCachedTexture * texture; string resname; }; @@ -183,7 +185,7 @@ private: WCache textureWCache; WCache sampleWCache; WCache psiWCache; - vector managedQuads; + vector managedQuads; //Statistics of record. unsigned int lastTime; diff --git a/projects/mtg/src/WCachedResource.cpp b/projects/mtg/src/WCachedResource.cpp index d0f54aeb5..ca5772960 100644 --- a/projects/mtg/src/WCachedResource.cpp +++ b/projects/mtg/src/WCachedResource.cpp @@ -66,12 +66,16 @@ WCachedTexture::~WCachedTexture(){ if(!trackedQuads.size()) return; - map::iterator it, nit; + vector::iterator it; + WTrackedQuad * tq = NULL; - for(it=trackedQuads.begin();it!=trackedQuads.end();it=nit){ - nit = it; - nit++; - trackedQuads.erase(it); + for(it=trackedQuads.begin();it!=trackedQuads.end();it++){ + tq = (*it); + if(!tq) + continue; + + SAFE_DELETE(tq->quad); + SAFE_DELETE(tq); } trackedQuads.clear(); } @@ -79,29 +83,52 @@ WCachedTexture::~WCachedTexture(){ JTexture * WCachedTexture::Actual(){ return texture; } +bool WCachedTexture::isLocked(){ + if(locks != WRES_UNLOCKED) + return true; + + for(vector::iterator it=trackedQuads.begin();it!=trackedQuads.end();it++){ + if((*it)->isLocked()) + return true; + } + + return false; +} bool WCachedTexture::ReleaseQuad(JQuad* quad){ #ifdef DEBUG_CACHE OutputDebugString("Quad released.\n"); #endif + if(quad == NULL) + return false; - for(map::iterator i = trackedQuads.begin();i!=trackedQuads.end();i++){ - if(i->first == quad ){ - unlock(); - trackedQuads.erase(i); - return true; + WTrackedQuad * tq = NULL; + for(vector::iterator it = trackedQuads.begin();it!=trackedQuads.end();it++){ + if((*it) && (*it)->quad == quad ){ + tq = (*it); + tq->unlock(); + + if(!tq->isLocked()){ + SAFE_DELETE(tq->quad); + SAFE_DELETE(tq); + trackedQuads.erase(it); + } + + return true; //Returns true when found, not released. } } return false; } -JQuad * WCachedTexture::GetQuad(float offX, float offY, float width, float height,string resname){ +WTrackedQuad * WCachedTexture::GetTrackedQuad(float offX, float offY, float width, float height,string resname){ if(texture == NULL) return NULL; - JQuad * jq = NULL; + bool allocated = false; + WTrackedQuad * tq = NULL; + JQuad * quad = NULL; - map::iterator it; + vector::iterator it; std::transform(resname.begin(),resname.end(),resname.begin(),::tolower); if(width == 0.0f || width > texture->mWidth) @@ -109,40 +136,73 @@ JQuad * WCachedTexture::GetQuad(float offX, float offY, float width, float heigh if(height == 0.0f || height > texture->mHeight) height = texture->mHeight; - for(it = trackedQuads.begin();it!=trackedQuads.end();it++){ - if(it->second == resname){ - jq = it->first; + if((*it) && (*it)->resname == resname){ + tq = (*it); + break; } } - if(jq == NULL){ - jq = NEW JQuad(texture,offX,offY,width,height); - if(!jq) { + if(tq == NULL){ + allocated = true; + tq = NEW WTrackedQuad(resname); + + if(!tq) { //Probably out of memory. Try again. resources.Cleanup(); - jq = NEW JQuad(texture,offX,offY,width,height); + tq = NEW WTrackedQuad(resname); + } + } + + if(tq == NULL) + return NULL; + + quad = tq->quad; + + if(quad == NULL){ + quad = NEW JQuad(texture,offX,offY,width,height); + if(!quad) { + //Probably out of memory. Try again. + resources.Cleanup(); + quad = NEW JQuad(texture,offX,offY,width,height); } - if(!jq) + if(!quad){ + if(allocated) + SAFE_DELETE(tq); return NULL; //Probably a crash. + } - trackedQuads[jq] = resname; - return jq; - }else{ + tq->quad = quad; + trackedQuads.push_back(tq); + return tq; + } + else{ //Update JQ's values to what we called this with. - jq->SetTextureRect(offX,offY,width,height); - return jq; + quad->SetTextureRect(offX,offY,width,height); + return tq; } return NULL; } + +JQuad * WCachedTexture::GetQuad(float offX, float offY, float width, float height,string resname){ + WTrackedQuad * tq = GetTrackedQuad(offX,offY,width,height,resname); + + if(tq) + return tq->quad; + + return NULL; +} + + JQuad * WCachedTexture::GetQuad(string resname){ - map::iterator it; + vector::iterator it; std::transform(resname.begin(),resname.end(),resname.begin(),::tolower); + for(it = trackedQuads.begin();it!=trackedQuads.end();it++){ - if(it->second == resname){ - return it->first; + if((*it) && (*it)->resname == resname){ + return (*it)->quad; } } @@ -181,9 +241,9 @@ void WCachedTexture::Refresh(string filename){ else SAFE_DELETE(old); - for(map::iterator it=trackedQuads.begin();it!=trackedQuads.end();it++){ - if(it->first) - it->first->mTex = texture; + for(vector::iterator it=trackedQuads.begin();it!=trackedQuads.end();it++){ + if((*it) && (*it)->quad) + (*it)->quad->mTex = texture; } } @@ -385,3 +445,35 @@ void WCachedParticles::Nullify(){ if(particles) particles = NULL; } + +//WTrackedQuad +void WTrackedQuad::Nullify() { + quad = NULL; +} + +#if defined DEBUG_CACHE +int WTrackedQuad::totalTracked = 0; +#endif + +unsigned long WTrackedQuad::size() { + return sizeof(JQuad); +} +bool WTrackedQuad::isGood(){ + return (quad != NULL); +} +WTrackedQuad::WTrackedQuad(string _resname) { +#if defined DEBUG_CACHE + OutputDebugString("Tracked quad created.\n"); + totalTracked++; +#endif + quad = NULL; resname = _resname; +} +WTrackedQuad::~WTrackedQuad() { +#if defined DEBUG_CACHE + char buf[512]; + totalTracked--; + sprintf(buf,"~WTrackedQuad(). %d left.\n",totalTracked); + OutputDebugString(buf); +#endif + if(quad) SAFE_DELETE(quad); +} diff --git a/projects/mtg/src/WResourceManager.cpp b/projects/mtg/src/WResourceManager.cpp index 779f35ab1..3ef8178e8 100644 --- a/projects/mtg/src/WResourceManager.cpp +++ b/projects/mtg/src/WResourceManager.cpp @@ -54,6 +54,7 @@ void WResourceManager::DebugRender(){ #ifdef DEBUG_CACHE if(debugMessage.size()) font->DrawString(debugMessage.c_str(), SCREEN_WIDTH-10,SCREEN_HEIGHT-25,JGETEXT_RIGHT); + #endif } @@ -161,6 +162,11 @@ WResourceManager::WResourceManager(){ WResourceManager::~WResourceManager(){ LOG("==Destroying WResourceManager=="); RemoveAll(); + for(vector::iterator it=managedQuads.begin();it!=managedQuads.end();it++){ + WManagedQuad* wm = *it; + SAFE_DELETE(wm); + } + managedQuads.clear(); LOG("==Successfully Destroyed WResourceManager=="); } @@ -199,10 +205,10 @@ int WResourceManager::CreateQuad(const string &quadName, const string &textureNa string resname = quadName; std::transform(resname.begin(),resname.end(),resname.begin(),::tolower); - vector::iterator it; + vector::iterator it; int pos = 0; for(it = managedQuads.begin();it!=managedQuads.end();it++,pos++){ - if(it->resname == resname) + if((*it)->resname == resname) return pos; } @@ -216,9 +222,10 @@ int WResourceManager::CreateQuad(const string &quadName, const string &textureNa JQuad * jq = jtex->GetQuad(x,y,width,height,quadName); if(jq){ - WManagedQuad mq; - mq.resname = resname; - mq.texture = jtex; + WManagedQuad * mq; + mq = NEW WManagedQuad(); + mq->resname = resname; + mq->texture = jtex; managedQuads.push_back(mq); } @@ -232,9 +239,9 @@ JQuad * WResourceManager::GetQuad(const string &quadName){ string lookup = quadName; std::transform(lookup.begin(),lookup.end(),lookup.begin(),::tolower); - for(vector::iterator it=managedQuads.begin();it!=managedQuads.end();it++){ - if(it->resname == lookup) - return it->texture->GetQuad(lookup); + for(vector::iterator it=managedQuads.begin();it!=managedQuads.end();it++){ + if((*it)->resname == lookup) + return (*it)->texture->GetQuad(lookup); } return NULL; @@ -244,11 +251,11 @@ JQuad * WResourceManager::GetQuad(int id){ if(id < 0 || id >= (int) managedQuads.size()) return NULL; - WCachedTexture * jtex = managedQuads[id].texture; + WCachedTexture * jtex = managedQuads[id]->texture; if(!jtex) return NULL; - return jtex->GetQuad(managedQuads[id].resname); + return jtex->GetQuad(managedQuads[id]->resname); } JQuad * WResourceManager::RetrieveTempQuad(string filename){ @@ -265,12 +272,26 @@ JQuad * WResourceManager::RetrieveQuad(string filename, float offX, float offY, return jq; } + //Aliases. + if(style == RETRIEVE_VRAM){ + submode = submode | TEXTURE_SUB_VRAM; + style = RETRIEVE_LOCK; + } + else if(style == RETRIEVE_THUMB){ + submode = submode | TEXTURE_SUB_THUMB; + style = RETRIEVE_NORMAL; + } + //Resname defaults to filename. if(!resname.size()) resname = filename; //No quad, but we have a managed texture for this! - WCachedTexture * jtex = textureWCache.Retrieve(filename,style,submode); + WCachedTexture * jtex = NULL; + if(style == RETRIEVE_MANAGE) + jtex = textureWCache.Retrieve(filename,RETRIEVE_MANAGE,submode); + else + jtex = textureWCache.Retrieve(filename,RETRIEVE_NORMAL,submode); //Somehow, jtex wasn't promoted. if(style == RETRIEVE_MANAGE && jtex && !jtex->isPermanent()) @@ -278,16 +299,26 @@ JQuad * WResourceManager::RetrieveQuad(string filename, float offX, float offY, //Make this quad, overwriting any similarly resname'd quads. if(jtex){ - jq = jtex->GetQuad(offX,offY,width,height,resname); - + WTrackedQuad * tq = jtex->GetTrackedQuad(offX,offY,width,height,resname); + + if(tq == NULL) + return NULL; + if(style == RETRIEVE_MANAGE && resname != ""){ - WManagedQuad mq; - mq.resname = resname; - mq.texture = jtex; + WManagedQuad * mq = NEW WManagedQuad(); + mq->resname = resname; + mq->texture = jtex; managedQuads.push_back(mq); } - return jq; + if(style == RETRIEVE_LOCK) + tq->lock(); + else if(style == RETRIEVE_UNLOCK) + tq->unlock(); + else if(style == RETRIEVE_MANAGE) + tq->deadbolt(); + + return tq->quad; } //Texture doesn't exist, so no quad.