Jeck - WResourceManager / Cache should now be leak free. Demo mode still crashes around EnstackBlocker.

This commit is contained in:
wagic.jeck
2009-09-18 01:20:46 +00:00
parent 6abd3cc160
commit 8ba34dafca
16 changed files with 794 additions and 594 deletions
Binary file not shown.
+1 -1
View File
@@ -13,7 +13,7 @@ class GuiCombat : public GuiLayer
GameObserver* go; GameObserver* go;
DamagerDamaged* active; DamagerDamaged* active;
AttackerDamaged* activeAtk; AttackerDamaged* activeAtk;
static JQuad* ok_quad; static JTexture* ok_tex;
Pos ok, enemy_avatar; Pos ok, enemy_avatar;
vector<AttackerDamaged*> attackers; vector<AttackerDamaged*> attackers;
DamagerDamaged* current; DamagerDamaged* current;
+1
View File
@@ -20,6 +20,7 @@ class hgeDistortionMesh;
class ShopItem:public JGuiObject{ class ShopItem:public JGuiObject{
private: private:
bool mHasFocus; bool mHasFocus;
bool mRelease;
JLBFont *mFont; JLBFont *mFont;
string mText; string mText;
float xy[8]; float xy[8];
+39 -12
View File
@@ -18,24 +18,47 @@ public:
virtual void Nullify()=0; //For when our size is 0, so we don't free anything by mistake. 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 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 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? bool isPermanent(); //Is the resource permanent?
void lock(); //Lock it.
void deadbolt(); //Make it permanent. 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. void hit(); //Update resource's last used time.
protected:
int loadedMode; //What submode settings were we loaded with? (For refresh) int loadedMode; //What submode settings were we loaded with? (For refresh)
unsigned int lastTime; //When was the last time we were hit? 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. 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<class cacheItem,class cacheActual> 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: public:
friend class WResourceManager; friend class WResourceManager;
template<class cacheItem,class cacheActual> friend class WCache; template<class cacheItem,class cacheActual> friend class WCache;
@@ -45,22 +68,27 @@ public:
void Refresh(string filename); void Refresh(string filename);
unsigned long size(); unsigned long size();
bool isGood(); bool isGood();
bool isLocked();
bool Attempt(string filename, int submode, int & error); bool Attempt(string filename, int submode, int & error);
bool compare(JTexture * t) {return (t == texture);}; bool compare(JTexture * t) {return (t == texture);};
void Nullify(); void Nullify();
JTexture * Actual(); //Return this texture as is. Does not make a new one. JTexture * Actual(); //Return this texture as is. Does not make a new one.
JQuad * GetQuad(string resname); 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. 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. bool ReleaseQuad(JQuad* quad); //We're done with this quad, so delete and stop tracking. True if existed.
protected: protected:
JTexture * texture; JTexture * texture;
bool bVRAM; bool bVRAM;
map<JQuad*,string> trackedQuads; vector<WTrackedQuad*> trackedQuads;
}; };
class WCachedParticles: public WResource{ class WCachedParticles: public WCachedResource{
public: public:
friend class WResourceManager; friend class WResourceManager;
template<class cacheItem,class cacheActual> friend class WCache; template<class cacheItem,class cacheActual> friend class WCache;
@@ -79,13 +107,12 @@ protected:
hgeParticleSystemInfo * particles; hgeParticleSystemInfo * particles;
}; };
class WCachedSample: public WResource{ class WCachedSample: public WCachedResource{
public: public:
friend class WResourceManager; friend class WResourceManager;
template<class cacheItem,class cacheActual> friend class WCache; template<class cacheItem,class cacheActual> friend class WCache;
WCachedSample(); WCachedSample();
~WCachedSample(); ~WCachedSample();
void Nullify(); void Nullify();
bool compare(JSample * s) {return (s == sample);}; bool compare(JSample * s) {return (s == sample);};
unsigned long size(); unsigned long size();
+16 -6
View File
@@ -7,17 +7,28 @@
#include "MTGCard.h" #include "MTGCard.h"
#include "WCachedResource.h" #include "WCachedResource.h"
//Hard Limits. //Soft limits.
#define HUGE_CACHE_LIMIT 10000000
#define HUGE_CACHE_ITEMS 400
#define LARGE_CACHE_LIMIT 5000000 #define LARGE_CACHE_LIMIT 5000000
#define SMALL_CACHE_LIMIT 2000000 #define LARGE_CACHE_ITEMS 300
#define MAX_CACHE_OBJECTS 200
#define SMALL_CACHE_LIMIT 1000000
#define SMALL_CACHE_ITEMS 200
//Hard Limits.
#define MAX_CACHE_OBJECTS 400
#define MAX_CACHE_ATTEMPTS 10 #define MAX_CACHE_ATTEMPTS 10
#define MAX_CACHE_MISSES 200 #define MAX_CACHE_MISSES 200
#define MAX_CACHED_SAMPLES 0
enum ENUM_WRES_INFO{ enum ENUM_WRES_INFO{
WRES_UNLOCKED = 0, //Resource is unlocked. WRES_UNLOCKED = 0, //Resource is unlocked.
WRES_MAX_LOCK = 250, //Maximum number of locks for a resource. WRES_MAX_LOCK = 250, //Maximum number of locks for a resource.
WRES_PERMANENT = 251, //Resource is permanent (ie, managed) WRES_PERMANENT = 251, //Resource is permanent (ie, managed)
WRES_UNDERLOCKED = 252, //Resource was released too many times.
}; };
enum ENUM_RETRIEVE_STYLE{ enum ENUM_RETRIEVE_STYLE{
@@ -166,8 +177,7 @@ public:
//Wrapped from JSoundSystem. TODO: Privatize. //Wrapped from JSoundSystem. TODO: Privatize.
JMusic * ssLoadMusic(const char *fileName); JMusic * ssLoadMusic(const char *fileName);
void LargeCache(); void CacheForState(int state);
void SmallCache();
void DebugRender(); void DebugRender();
@@ -183,7 +193,7 @@ private:
WCache<WCachedTexture,JTexture> textureWCache; WCache<WCachedTexture,JTexture> textureWCache;
WCache<WCachedSample,JSample> sampleWCache; WCache<WCachedSample,JSample> sampleWCache;
WCache<WCachedParticles,hgeParticleSystemInfo> psiWCache; WCache<WCachedParticles,hgeParticleSystemInfo> psiWCache;
vector<WManagedQuad> managedQuads; vector<WManagedQuad*> managedQuads;
//Statistics of record. //Statistics of record.
unsigned int lastTime; unsigned int lastTime;
+8
View File
@@ -249,6 +249,14 @@ void GameApp::Update()
mCurrentState = mNextState; mCurrentState = mNextState;
//Automate cache resizing.
for(int x=0;x<MAX_STATE;x++){
if(mNextState == mGameStates[x]){
resources.CacheForState(x);
break;
}
}
#if defined (WIN32) || defined (LINUX) #if defined (WIN32) || defined (LINUX)
#else #else
-4
View File
@@ -42,7 +42,6 @@ GameStateDuel::GameStateDuel(GameApp* parent): GameState(parent) {
deck[i]=NULL; deck[i]=NULL;
mPlayers[i]=NULL; mPlayers[i]=NULL;
} }
resources.LargeCache();
premadeDeck = false; premadeDeck = false;
game = NULL; game = NULL;
deckmenu = NULL; deckmenu = NULL;
@@ -63,7 +62,6 @@ GameStateDuel::~GameStateDuel() {
void GameStateDuel::Start() void GameStateDuel::Start()
{ {
JRenderer * renderer = JRenderer::GetInstance(); JRenderer * renderer = JRenderer::GetInstance();
resources.SmallCache();
renderer->ResetPrivateVRAM(); renderer->ResetPrivateVRAM();
renderer->EnableVSync(true); renderer->EnableVSync(true);
@@ -73,7 +71,6 @@ void GameStateDuel::Start()
testSuite = NEW TestSuite(RESPATH"/test/_tests.txt",mParent->collection); testSuite = NEW TestSuite(RESPATH"/test/_tests.txt",mParent->collection);
#endif #endif
mGamePhase = DUEL_STATE_CHOOSE_DECK1; mGamePhase = DUEL_STATE_CHOOSE_DECK1;
credits = NEW Credits(); credits = NEW Credits();
mFont = resources.GetJLBFont(Constants::MENU_FONT); mFont = resources.GetJLBFont(Constants::MENU_FONT);
@@ -218,7 +215,6 @@ void GameStateDuel::End()
#if defined (WIN32) || defined (LINUX) #if defined (WIN32) || defined (LINUX)
OutputDebugString("Ending GamestateDuel\n"); OutputDebugString("Ending GamestateDuel\n");
#endif #endif
resources.SmallCache();
SAFE_DELETE(deckmenu); SAFE_DELETE(deckmenu);
JRenderer::GetInstance()->EnableVSync(false); JRenderer::GetInstance()->EnableVSync(false);
if (mPlayers[0] && mPlayers[1]) mPlayers[0]->End(); if (mPlayers[0] && mPlayers[1]) mPlayers[0]->End();
+1
View File
@@ -119,6 +119,7 @@ void GameStateShop::load(){
void GameStateShop::End() void GameStateShop::End()
{ {
JRenderer::GetInstance()->EnableVSync(false); JRenderer::GetInstance()->EnableVSync(false);
resources.Release(mBg);
resources.Release(bgTexture); resources.Release(bgTexture);
SAFE_DELETE(shop); SAFE_DELETE(shop);
SAFE_DELETE(menu); SAFE_DELETE(menu);
+10 -7
View File
@@ -12,24 +12,23 @@ struct Left : public Exp { static inline bool test(DamagerDamaged* ref, DamagerD
struct Right : public Exp { static inline bool test(DamagerDamaged* ref, DamagerDamaged* test) struct Right : public Exp { static inline bool test(DamagerDamaged* ref, DamagerDamaged* test)
{ return ref->y == test->y && ref->x < test->x && test->show; } }; { return ref->y == test->y && ref->x < test->x && test->show; } };
JQuad* GuiCombat::ok_quad = NULL; JTexture* GuiCombat::ok_tex = NULL;
GuiCombat::GuiCombat(GameObserver* go) : GuiLayer(), go(go), active(false), activeAtk(NULL), GuiCombat::GuiCombat(GameObserver* go) : GuiLayer(), go(go), active(false), activeAtk(NULL),
ok(SCREEN_WIDTH - MARGIN, 210, 1, 0, 255), ok(SCREEN_WIDTH - MARGIN, 210, 1, 0, 255),
enemy_avatar(SCREEN_WIDTH - MARGIN, TOP_LINE, 2, 0, 255), enemy_avatar(SCREEN_WIDTH - MARGIN, TOP_LINE, 2, 0, 255),
cursor_pos(NONE), step(DAMAGE) cursor_pos(NONE), step(DAMAGE)
{ {
if(NULL == ok_quad) if(NULL == ok_tex)
{ {
ok_quad = resources.RetrieveQuad("Ok.png"); ok_tex = resources.RetrieveTexture("Ok.png",RETRIEVE_LOCK);
if (ok_quad) ok_quad->SetHotSpot(28, 22);
} }
} }
GuiCombat::~GuiCombat() GuiCombat::~GuiCombat()
{ {
if(ok_quad) if(ok_tex)
resources.Release(ok_quad); resources.Release(ok_tex);
for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it) for (inner_iterator it = attackers.begin(); it != attackers.end(); ++it)
{ {
@@ -277,7 +276,11 @@ void GuiCombat::Render()
} }
} }
} }
if (ok_quad) ok.Render(ok_quad); if (ok_tex) {
JQuad *ok_quad = resources.RetrieveTempQuad("Ok.png");
ok_quad->SetHotSpot(28, 22);
ok.Render(ok_quad);
}
renderer->DrawLine(0, SCREEN_HEIGHT / 2 + 10, SCREEN_WIDTH, SCREEN_HEIGHT / 2 + 10, ARGB(255, 255, 64, 0)); renderer->DrawLine(0, SCREEN_HEIGHT / 2 + 10, SCREEN_WIDTH, SCREEN_HEIGHT / 2 + 10, ARGB(255, 255, 64, 0));
if (FIRST_STRIKE == step) if (FIRST_STRIKE == step)
{ {
+5 -3
View File
@@ -41,6 +41,8 @@ ManaIcon::ManaIcon(int color, float x, float y) : Pos(x, y, 0.5, 0.0, 255), f(-1
if(!psi){ if(!psi){
psi = NEW hgeParticleSystemInfo(); psi = NEW hgeParticleSystemInfo();
if(!psi)
return;
hgeParticleSystemInfo * defaults = resources.RetrievePSI("mana.psi",mq); hgeParticleSystemInfo * defaults = resources.RetrievePSI("mana.psi",mq);
if(defaults){ if(defaults){
memcpy(psi,defaults,sizeof(hgeParticleSystemInfo)); memcpy(psi,defaults,sizeof(hgeParticleSystemInfo));
@@ -50,7 +52,7 @@ ManaIcon::ManaIcon(int color, float x, float y) : Pos(x, y, 0.5, 0.0, 255), f(-1
//Default values for particle system! Cribbed from mana.psi //Default values for particle system! Cribbed from mana.psi
//Really, we should just be loading that and then changing colors... //Really, we should just be loading that and then changing colors...
/*psi->nEmission = 114; psi->nEmission = 114;
psi->fLifetime = -1; psi->fLifetime = -1;
psi->fParticleLifeMin = 1.1507937; psi->fParticleLifeMin = 1.1507937;
psi->fParticleLifeMax = 1.4682540; psi->fParticleLifeMax = 1.4682540;
@@ -60,7 +62,7 @@ ManaIcon::ManaIcon(int color, float x, float y) : Pos(x, y, 0.5, 0.0, 255), f(-1
psi->fSizeVar = 0.25396827; psi->fSizeVar = 0.25396827;
psi->fSpinStart = -5.5555553; psi->fSpinStart = -5.5555553;
psi->fAlphaVar = 0.77777779; psi->fAlphaVar = 0.77777779;
psi->sprite = mq;*/ psi->sprite = mq;
} }
switch(color){ switch(color){
@@ -91,7 +93,7 @@ ManaIcon::ManaIcon(int color, float x, float y) : Pos(x, y, 0.5, 0.0, 255), f(-1
} }
particleSys = NEW hgeParticleSystem(psi); particleSys = NEW hgeParticleSystem(psi);
SAFE_DELETE(psi); //Not handled by cache, so kill it here. SAFE_DELETE(psi); //This version of psi is not handled by cache, so kill it here.
} }
else else
particleSys = NEW hgeParticleSystem(psi); //Cache will clean psi up later. particleSys = NEW hgeParticleSystem(psi); //Cache will clean psi up later.
+2 -1
View File
@@ -76,7 +76,8 @@ void GuiPlay::BattleField::EnstackAttacker(CardView* card)
void GuiPlay::BattleField::EnstackBlocker(CardView* card) void GuiPlay::BattleField::EnstackBlocker(CardView* card)
{ {
GameObserver* game = GameObserver::GetInstance(); GameObserver* game = GameObserver::GetInstance();
if (card->card && card->card->defenser && card->card->defenser->view) card->x = card->card->defenser->view->x; if (card->card && card->card->defenser && card->card->defenser->view)
card->x = card->card->defenser->view->x;
card->y = baseY + (game->players[0] == card->card->controller() ? 20 + y : -20 - y); card->y = baseY + (game->players[0] == card->card->controller() ? 20 + y : -20 - y);
} }
void GuiPlay::BattleField::Update(float dt) void GuiPlay::BattleField::Update(float dt)
+3 -1
View File
@@ -26,6 +26,8 @@ Player::~Player(){
SAFE_DELETE(manaPool); SAFE_DELETE(manaPool);
resources.Release(mAvatar); resources.Release(mAvatar);
resources.Release(mAvatarTex); resources.Release(mAvatarTex);
mAvatar = NULL;
mAvatarTex = NULL;
} }
const string Player::getDisplayName() const { const string Player::getDisplayName() const {
@@ -59,7 +61,7 @@ Player * Player::opponent(){
HumanPlayer::HumanPlayer(MTGPlayerCards * deck, string file, string fileSmall) : Player(deck, file, fileSmall) { HumanPlayer::HumanPlayer(MTGPlayerCards * deck, string file, string fileSmall) : Player(deck, file, fileSmall) {
mAvatarTex = resources.RetrieveTexture("avatar.jpg",RETRIEVE_VRAM,TEXTURE_SUB_AVATAR); mAvatarTex = resources.RetrieveTexture("avatar.jpg",RETRIEVE_VRAM,TEXTURE_SUB_AVATAR);
if (mAvatarTex) if (mAvatarTex)
mAvatar = resources.RetrieveQuad("avatar.jpg",0,0,35,50,"playerAvatar",RETRIEVE_NORMAL,TEXTURE_SUB_AVATAR); mAvatar = resources.RetrieveQuad("avatar.jpg",0,0,35,50,"playerAvatar",RETRIEVE_VRAM,TEXTURE_SUB_AVATAR);
else else
mAvatar = NULL; mAvatar = NULL;
} }
+10 -2
View File
@@ -29,6 +29,7 @@ ShopItem::ShopItem(int id, JLBFont *font, char* text, JQuad * _quad,JQuad * _thu
quantity = 10; quantity = 10;
card = NULL; card = NULL;
mHasFocus = hasFocus; mHasFocus = hasFocus;
mRelease = false;
mScale = 1.0f; mScale = 1.0f;
mTargetScale = 1.0f; mTargetScale = 1.0f;
@@ -56,6 +57,7 @@ ShopItem::ShopItem(int id, JLBFont *font, int _cardid, float _xy[], bool hasFocu
xy[i] = _xy[i]; xy[i] = _xy[i];
} }
mHasFocus = hasFocus; mHasFocus = hasFocus;
mRelease = false;
mScale = 1.0f; mScale = 1.0f;
mTargetScale = 1.0f; mTargetScale = 1.0f;
@@ -69,9 +71,12 @@ ShopItem::ShopItem(int id, JLBFont *font, int _cardid, float _xy[], bool hasFocu
if (card->getRarity() == Constants::RARITY_L) quantity = 50; if (card->getRarity() == Constants::RARITY_L) quantity = 50;
quad = NULL; quad = NULL;
thumb = resources.RetrieveCard(card,CACHE_THUMB); thumb = resources.RetrieveCard(card,RETRIEVE_LOCK,TEXTURE_SUB_THUMB);
if (!thumb) thumb = CardGui::alternateThumbQuad(card); if (!thumb)
thumb = CardGui::alternateThumbQuad(card);
else
mRelease = true;
if (thumb){ if (thumb){
mesh=NEW hgeDistortionMesh(2,2); mesh=NEW hgeDistortionMesh(2,2);
@@ -102,6 +107,9 @@ int ShopItem::updateCount(DeckDataWrapper * ddw){
ShopItem::~ShopItem(){ ShopItem::~ShopItem(){
OutputDebugString("delete shopitem\n"); OutputDebugString("delete shopitem\n");
if(mRelease){
resources.Release(thumb);
}
SAFE_DELETE(mesh); SAFE_DELETE(mesh);
} }
+1 -1
View File
@@ -15,7 +15,7 @@ TestSuiteAI::TestSuiteAI(TestSuite * _suite, int playerId):AIPlayer(_suite->buil
mAvatarTex = resources.RetrieveTexture("baka.jpg",RETRIEVE_VRAM,TEXTURE_SUB_AVATAR); mAvatarTex = resources.RetrieveTexture("baka.jpg",RETRIEVE_VRAM,TEXTURE_SUB_AVATAR);
if(mAvatarTex) if(mAvatarTex)
mAvatar = resources.RetrieveQuad("baka.jpg", 0, 0, 35, 50,"bakaAvatar",RETRIEVE_NORMAL,TEXTURE_SUB_AVATAR); mAvatar = resources.RetrieveQuad("baka.jpg", 0, 0, 35, 50,"bakaAvatar",RETRIEVE_VRAM,TEXTURE_SUB_AVATAR);
else else
mAvatar = NULL; mAvatar = NULL;
+133 -35
View File
@@ -9,8 +9,10 @@
#include "../include/GameOptions.h" #include "../include/GameOptions.h"
#include "../include/WResourceManager.h" #include "../include/WResourceManager.h"
//WResource //WResource
WResource::~WResource(){ WResource::~WResource(){
OutputDebugString("~WResource()\n");
return; return;
} }
WResource::WResource(){ WResource::WResource(){
@@ -40,9 +42,18 @@ void WResource::lock(){
void WResource::unlock(bool force){ void WResource::unlock(bool force){
if(force) if(force)
locks = 0; locks = 0;
else if(locks > WRES_UNLOCKED && locks <= WRES_MAX_LOCK) else if(locks > WRES_UNLOCKED){
if(locks <= WRES_MAX_LOCK)
locks--; locks--;
} }
else
#ifdef DEBUG_CACHE
locks = WRES_UNDERLOCKED;
#else
locks = 0;
#endif
}
void WResource::hit(){ void WResource::hit(){
lastTime = resources.nowTime(); lastTime = resources.nowTime();
@@ -66,12 +77,12 @@ WCachedTexture::~WCachedTexture(){
if(!trackedQuads.size()) if(!trackedQuads.size())
return; return;
map<JQuad*,string>::iterator it, nit; vector<WTrackedQuad*>::iterator it;
WTrackedQuad * tq = NULL;
for(it=trackedQuads.begin();it!=trackedQuads.end();it=nit){ for(it=trackedQuads.begin();it!=trackedQuads.end();it++){
nit = it; tq = (*it);
nit++; SAFE_DELETE(tq);
trackedQuads.erase(it);
} }
trackedQuads.clear(); trackedQuads.clear();
} }
@@ -79,29 +90,57 @@ WCachedTexture::~WCachedTexture(){
JTexture * WCachedTexture::Actual(){ JTexture * WCachedTexture::Actual(){
return texture; return texture;
} }
bool WCachedTexture::isLocked(){
if(locks != WRES_UNLOCKED)
return true;
for(vector<WTrackedQuad*>::iterator it=trackedQuads.begin();it!=trackedQuads.end();it++){
if((*it)->isLocked())
return true;
}
return false;
}
bool WCachedTexture::ReleaseQuad(JQuad* quad){ bool WCachedTexture::ReleaseQuad(JQuad* quad){
#ifdef DEBUG_CACHE #ifdef DEBUG_CACHE
OutputDebugString("Quad released.\n"); char buf[512];
#endif
for(map<JQuad*,string>::iterator i = trackedQuads.begin();i!=trackedQuads.end();i++){ sprintf(buf,"ReleaseQuad: %d.\n", (int) quad);
if(i->first == quad ){ OutputDebugString(buf);
unlock(); #endif
trackedQuads.erase(i); if(quad == NULL)
return true; return false;
WTrackedQuad * tq = NULL;
vector<WTrackedQuad*>::iterator nit;
for(vector<WTrackedQuad*>::iterator it = trackedQuads.begin();it!=trackedQuads.end();it=nit){
nit = it;
nit++;
if((*it) && (*it)->quad == quad ){
tq = (*it);
tq->unlock();
if(!tq->isLocked()){
SAFE_DELETE(tq);
trackedQuads.erase(it);
}
return true; //Returns true when found.
} }
} }
return false; 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) if(texture == NULL)
return NULL; return NULL;
JQuad * jq = NULL; bool allocated = false;
WTrackedQuad * tq = NULL;
JQuad * quad = NULL;
map<JQuad*,string>::iterator it; vector<WTrackedQuad*>::iterator it;
std::transform(resname.begin(),resname.end(),resname.begin(),::tolower); std::transform(resname.begin(),resname.end(),resname.begin(),::tolower);
if(width == 0.0f || width > texture->mWidth) if(width == 0.0f || width > texture->mWidth)
@@ -109,40 +148,67 @@ JQuad * WCachedTexture::GetQuad(float offX, float offY, float width, float heigh
if(height == 0.0f || height > texture->mHeight) if(height == 0.0f || height > texture->mHeight)
height = texture->mHeight; height = texture->mHeight;
for(it = trackedQuads.begin();it!=trackedQuads.end();it++){ for(it = trackedQuads.begin();it!=trackedQuads.end();it++){
if(it->second == resname){ if((*it) && (*it)->resname == resname){
jq = it->first; tq = (*it);
break;
} }
} }
if(jq == NULL){ if(tq == NULL){
jq = NEW JQuad(texture,offX,offY,width,height); allocated = true;
if(!jq) { 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. //Probably out of memory. Try again.
resources.Cleanup(); resources.Cleanup();
jq = NEW JQuad(texture,offX,offY,width,height); quad = NEW JQuad(texture,offX,offY,width,height);
} }
if(!jq) if(!quad){
if(allocated && tq)
SAFE_DELETE(tq);
return NULL; //Probably a crash. return NULL; //Probably a crash.
}
trackedQuads[jq] = resname; tq->quad = quad;
return jq; trackedQuads.push_back(tq);
}else{ return tq;
}
else{
//Update JQ's values to what we called this with. //Update JQ's values to what we called this with.
jq->SetTextureRect(offX,offY,width,height); quad->SetTextureRect(offX,offY,width,height);
return jq; return tq;
} }
return NULL; 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){ JQuad * WCachedTexture::GetQuad(string resname){
map<JQuad*,string>::iterator it; vector<WTrackedQuad*>::iterator it;
std::transform(resname.begin(),resname.end(),resname.begin(),::tolower); std::transform(resname.begin(),resname.end(),resname.begin(),::tolower);
for(it = trackedQuads.begin();it!=trackedQuads.end();it++){ for(it = trackedQuads.begin();it!=trackedQuads.end();it++){
if(it->second == resname){ if((*it) && (*it)->resname == resname){
return it->first; return (*it)->quad;
} }
} }
@@ -181,9 +247,9 @@ void WCachedTexture::Refresh(string filename){
else else
SAFE_DELETE(old); SAFE_DELETE(old);
for(map<JQuad*,string>::iterator it=trackedQuads.begin();it!=trackedQuads.end();it++){ for(vector<WTrackedQuad*>::iterator it=trackedQuads.begin();it!=trackedQuads.end();it++){
if(it->first) if((*it) && (*it)->quad)
it->first->mTex = texture; (*it)->quad->mTex = texture;
} }
} }
@@ -385,3 +451,35 @@ void WCachedParticles::Nullify(){
if(particles) if(particles)
particles = NULL; 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("WTrackedQuad().\n");
totalTracked++;
#endif
quad = NULL; resname = _resname;
}
WTrackedQuad::~WTrackedQuad() {
#if defined DEBUG_CACHE
char buf[512];
totalTracked--;
sprintf(buf,"~WTrackedQuad() {%d}. %d left.\n", (int) quad,totalTracked);
OutputDebugString(buf);
#endif
if(quad) SAFE_DELETE(quad);
}
+98 -55
View File
@@ -41,9 +41,9 @@ void WResourceManager::DebugRender(){
if(textureWCache.totalSize > textureWCache.cacheSize) if(textureWCache.totalSize > textureWCache.cacheSize)
man = textureWCache.totalSize - textureWCache.cacheSize; man = textureWCache.totalSize - textureWCache.cacheSize;
sprintf(buf,"Textures %u+%u (of %u) items (%u misses), Pixels: %lu+%lu (of %lu)", sprintf(buf,"Textures %u+%u (of %u) items (%u misses), Pixels: %lu (of %lu) + %lu",
textureWCache.cacheItems, textureWCache.managed.size(),textureWCache.maxCached, textureWCache.cacheItems, textureWCache.managed.size(),textureWCache.maxCached,
misses,textureWCache.cacheSize,man,textureWCache.maxCacheSize); misses,textureWCache.cacheSize,textureWCache.maxCacheSize,man);
font->DrawString(buf, 10,5); font->DrawString(buf, 10,5);
@@ -54,6 +54,7 @@ void WResourceManager::DebugRender(){
#ifdef DEBUG_CACHE #ifdef DEBUG_CACHE
if(debugMessage.size()) if(debugMessage.size())
font->DrawString(debugMessage.c_str(), SCREEN_WIDTH-10,SCREEN_HEIGHT-25,JGETEXT_RIGHT); font->DrawString(debugMessage.c_str(), SCREEN_WIDTH-10,SCREEN_HEIGHT-25,JGETEXT_RIGHT);
#endif #endif
} }
@@ -154,13 +155,19 @@ WResourceManager::WResourceManager(){
mFontMap.clear(); mFontMap.clear();
psiWCache.Resize(SMALL_CACHE_LIMIT,6); //Plenty of room for mana symbols, or whatever. psiWCache.Resize(SMALL_CACHE_LIMIT,6); //Plenty of room for mana symbols, or whatever.
sampleWCache.Resize(SMALL_CACHE_LIMIT,0); //This guy only exists so we can track misses. sampleWCache.Resize(SMALL_CACHE_LIMIT,MAX_CACHED_SAMPLES);
textureWCache.Resize(LARGE_CACHE_LIMIT,MAX_CACHE_OBJECTS); textureWCache.Resize(LARGE_CACHE_LIMIT,MAX_CACHE_OBJECTS);
lastTime = 0; lastTime = 0;
} }
WResourceManager::~WResourceManager(){ WResourceManager::~WResourceManager(){
LOG("==Destroying WResourceManager=="); LOG("==Destroying WResourceManager==");
RemoveAll(); RemoveAll();
for(vector<WManagedQuad*>::iterator it=managedQuads.begin();it!=managedQuads.end();it++){
WManagedQuad* wm = *it;
SAFE_DELETE(wm);
}
managedQuads.clear();
LOG("==Successfully Destroyed WResourceManager=="); LOG("==Successfully Destroyed WResourceManager==");
} }
@@ -172,22 +179,12 @@ JQuad * WResourceManager::RetrieveCard(MTGCard * card, int style, int submode){
string filename = card->getSetName(); string filename = card->getSetName();
filename += "/"; filename += "/";
filename += card->getImageName(); filename += card->getImageName();
WCachedTexture * res = NULL; JQuad * jq = RetrieveQuad(filename,0,0,0,0,filename,style,submode|TEXTURE_SUB_5551);
//Aliases. if(jq){
if(style == RETRIEVE_VRAM){ jq->SetHotSpot(jq->mTex->mWidth / 2, jq->mTex->mHeight / 2);
submode = submode | TEXTURE_SUB_VRAM; return jq;
style = RETRIEVE_LOCK;
} }
else if(style == RETRIEVE_THUMB){
submode = submode | TEXTURE_SUB_THUMB;
style = RETRIEVE_NORMAL;
}
res = textureWCache.Retrieve(filename,style,submode|TEXTURE_SUB_5551); //Force RGBA5650. JPG doesn't support transparency anyways.
if(res) //A non-null result will always be good.
return res->GetCard();
return NULL; return NULL;
} }
@@ -199,10 +196,10 @@ int WResourceManager::CreateQuad(const string &quadName, const string &textureNa
string resname = quadName; string resname = quadName;
std::transform(resname.begin(),resname.end(),resname.begin(),::tolower); std::transform(resname.begin(),resname.end(),resname.begin(),::tolower);
vector<WManagedQuad>::iterator it; vector<WManagedQuad*>::iterator it;
int pos = 0; int pos = 0;
for(it = managedQuads.begin();it!=managedQuads.end();it++,pos++){ for(it = managedQuads.begin();it!=managedQuads.end();it++,pos++){
if(it->resname == resname) if((*it)->resname == resname)
return pos; return pos;
} }
@@ -213,12 +210,14 @@ int WResourceManager::CreateQuad(const string &quadName, const string &textureNa
return INVALID_ID; return INVALID_ID;
if(jtex){ if(jtex){
JQuad * jq = jtex->GetQuad(x,y,width,height,quadName); WTrackedQuad * tq = jtex->GetTrackedQuad(x,y,width,height,quadName);
if(jq){ if(tq){
WManagedQuad mq; tq->deadbolt();
mq.resname = resname; WManagedQuad * mq;
mq.texture = jtex; mq = NEW WManagedQuad();
mq->resname = resname;
mq->texture = jtex;
managedQuads.push_back(mq); managedQuads.push_back(mq);
} }
@@ -232,9 +231,9 @@ JQuad * WResourceManager::GetQuad(const string &quadName){
string lookup = quadName; string lookup = quadName;
std::transform(lookup.begin(),lookup.end(),lookup.begin(),::tolower); std::transform(lookup.begin(),lookup.end(),lookup.begin(),::tolower);
for(vector<WManagedQuad>::iterator it=managedQuads.begin();it!=managedQuads.end();it++){ for(vector<WManagedQuad*>::iterator it=managedQuads.begin();it!=managedQuads.end();it++){
if(it->resname == lookup) if((*it)->resname == lookup)
return it->texture->GetQuad(lookup); return (*it)->texture->GetQuad(lookup);
} }
return NULL; return NULL;
@@ -244,11 +243,11 @@ JQuad * WResourceManager::GetQuad(int id){
if(id < 0 || id >= (int) managedQuads.size()) if(id < 0 || id >= (int) managedQuads.size())
return NULL; return NULL;
WCachedTexture * jtex = managedQuads[id].texture; WCachedTexture * jtex = managedQuads[id]->texture;
if(!jtex) if(!jtex)
return NULL; return NULL;
return jtex->GetQuad(managedQuads[id].resname); return jtex->GetQuad(managedQuads[id]->resname);
} }
JQuad * WResourceManager::RetrieveTempQuad(string filename){ JQuad * WResourceManager::RetrieveTempQuad(string filename){
@@ -265,12 +264,28 @@ JQuad * WResourceManager::RetrieveQuad(string filename, float offX, float offY,
return jq; 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. //Resname defaults to filename.
if(!resname.size()) if(!resname.size())
resname = filename; resname = filename;
//No quad, but we have a managed texture for this! //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 if(style == RETRIEVE_EXISTING)
jtex = textureWCache.Retrieve(filename,RETRIEVE_EXISTING,submode);
else
jtex = textureWCache.Retrieve(filename,RETRIEVE_NORMAL,submode);
//Somehow, jtex wasn't promoted. //Somehow, jtex wasn't promoted.
if(style == RETRIEVE_MANAGE && jtex && !jtex->isPermanent()) if(style == RETRIEVE_MANAGE && jtex && !jtex->isPermanent())
@@ -278,16 +293,26 @@ JQuad * WResourceManager::RetrieveQuad(string filename, float offX, float offY,
//Make this quad, overwriting any similarly resname'd quads. //Make this quad, overwriting any similarly resname'd quads.
if(jtex){ 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 != ""){ if(style == RETRIEVE_MANAGE && resname != ""){
WManagedQuad mq; WManagedQuad * mq = NEW WManagedQuad();
mq.resname = resname; mq->resname = resname;
mq.texture = jtex; mq->texture = jtex;
managedQuads.push_back(mq); 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. //Texture doesn't exist, so no quad.
@@ -310,8 +335,9 @@ void WResourceManager::Release(JQuad * quad){
break; break;
} }
if(it != textureWCache.cache.end() && it->second) //Releasing a quad doesn't release the associated texture-- it might be needed later.
textureWCache.RemoveItem(it->second,false); //won't remove locked. //if(it != textureWCache.cache.end() && it->second)
// textureWCache.RemoveItem(it->second,false); //won't remove locked.
} }
void WResourceManager::ClearMisses(){ void WResourceManager::ClearMisses(){
@@ -444,6 +470,7 @@ hgeParticleSystemInfo * WResourceManager::RetrievePSI(string filename, JQuad * t
JSample * WResourceManager::RetrieveSample(string filename, int style, int submode){ JSample * WResourceManager::RetrieveSample(string filename, int style, int submode){
//Check cache. This just tracks misses. //Check cache. This just tracks misses.
return NULL;
WCachedSample * tc = NULL; WCachedSample * tc = NULL;
tc = sampleWCache.Get(filename,submode); tc = sampleWCache.Get(filename,submode);
@@ -747,23 +774,32 @@ int WResourceManager::LoadJLBFont(const string &fontName, int height){
else else
return itr->second; return itr->second;
} }
void WResourceManager::LargeCache(){ void WResourceManager::CacheForState(int state){
#if (defined WIN32 || defined LINUX) && !defined DEBUG_CACHE #if (defined WIN32 || defined LINUX) && !defined DEBUG_CACHE
textureWCache.Resize(HUGE_CACHE_LIMIT,HUGE_CACHE_ITEMS);
return; return;
#else #else
//Does not check option so we can use large cache during switch(state){
//deck editor, when it's pretty much always safe. //Default is not to change cache sizes.
textureWCache.Resize(LARGE_CACHE_LIMIT,MAX_CACHE_OBJECTS); case GAME_STATE_MENU:
textureWCache.Cleanup(); case GAME_STATE_OPTIONS:
#endif break;
//Duels use a smaller cache, so there's more room for game stuff.
case GAME_STATE_DUEL:
textureWCache.Resize(SMALL_CACHE_LIMIT,SMALL_CACHE_ITEMS);
sampleWCache.Resize(SMALL_CACHE_LIMIT,MAX_CACHED_SAMPLES);
Cleanup();
break;
//Deck editor and shop are entirely cache safe, so give it near infinite resources.
case GAME_STATE_SHOP:
case GAME_STATE_DECK_VIEWER:
textureWCache.Resize(HUGE_CACHE_LIMIT,HUGE_CACHE_ITEMS);
break;
//Anything unknown, use large cache.
default:
textureWCache.Resize(LARGE_CACHE_LIMIT,LARGE_CACHE_ITEMS);
break;
} }
void WResourceManager::SmallCache(){
#if (defined WIN32 || defined LINUX) && !defined DEBUG_CACHE
return;
#else
if(options[Options::CACHESIZE].number == 0){
textureWCache.Resize(SMALL_CACHE_LIMIT,MAX_CACHE_OBJECTS);
textureWCache.Cleanup();}
#endif #endif
} }
@@ -949,8 +985,6 @@ void WCache<cacheItem, cacheActual>::Resize(unsigned long size, int items){
} }
template <class cacheItem, class cacheActual> template <class cacheItem, class cacheActual>
cacheItem* WCache<cacheItem, cacheActual>::AttemptNew(string filename, int submode){ cacheItem* WCache<cacheItem, cacheActual>::AttemptNew(string filename, int submode){
// Cleanup();
if(submode & CACHE_EXISTING){ //Should never get this far. if(submode & CACHE_EXISTING){ //Should never get this far.
mError = CACHE_ERROR_NOT_CACHED; mError = CACHE_ERROR_NOT_CACHED;
return NULL; return NULL;
@@ -962,7 +996,7 @@ cacheItem* WCache<cacheItem, cacheActual>::AttemptNew(string filename, int submo
if(item == NULL || !item->Attempt(filename,submode,mError)){ if(item == NULL || !item->Attempt(filename,submode,mError)){
//No such file. Fail. //No such file. Fail.
if(mError == CACHE_ERROR_404){ if(item && mError == CACHE_ERROR_404){
Delete(item); Delete(item);
return NULL; return NULL;
} }
@@ -1002,7 +1036,9 @@ cacheItem* WCache<cacheItem, cacheActual>::AttemptNew(string filename, int submo
else else
mError = CACHE_ERROR_NONE; mError = CACHE_ERROR_NONE;
item->lock();
Cleanup(); Cleanup();
item->unlock();
return item; return item;
} }
@@ -1189,6 +1225,9 @@ cacheItem * WCache<cacheItem, cacheActual>::Get(string id, int style, int submod
cacheSize += isize; cacheSize += isize;
} }
item->lock();
Cleanup(); //Strictly enforce limits.
item->unlock();
return item; return item;
} }
@@ -1297,7 +1336,7 @@ bool WCache<cacheItem, cacheActual>::RemoveMiss(string id){
template <class cacheItem, class cacheActual> template <class cacheItem, class cacheActual>
bool WCache<cacheItem, cacheActual>::RemoveItem(cacheItem * item, bool force){ bool WCache<cacheItem, cacheActual>::RemoveItem(cacheItem * item, bool force){
typename map<string,cacheItem*>::iterator it = cache.end(); typename map<string,cacheItem*>::iterator it;
if(item == NULL) if(item == NULL)
return false; //Use RemoveMiss to remove cache misses, not this. return false; //Use RemoveMiss to remove cache misses, not this.
@@ -1351,7 +1390,11 @@ template <class cacheItem, class cacheActual>
bool WCache<cacheItem, cacheActual>::Delete(cacheItem * item){ bool WCache<cacheItem, cacheActual>::Delete(cacheItem * item){
if(!item) if(!item)
return false; return false;
#ifdef DEBUG_CACHE
char buf[512];
sprintf(buf,"Cache: Delete [%d]\n",(int)item);
//OutputDebugString(buf);
#endif
if(maxCached == 0) if(maxCached == 0)
item->Nullify(); item->Nullify();