diff options
author | Andrei Karas <akaras@inbox.ru> | 2011-08-01 21:05:48 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2011-08-02 18:38:14 +0300 |
commit | aac238cec9cab9efe7319d8397b95e7a77bdb5cd (patch) | |
tree | 3298f3b604d4d45cc6d04f871f6a1abb29cdd554 | |
parent | 4e7096f15eba73e6ea28066df6ab389aab3f052c (diff) | |
download | mv-aac238cec9cab9efe7319d8397b95e7a77bdb5cd.tar.gz mv-aac238cec9cab9efe7319d8397b95e7a77bdb5cd.tar.bz2 mv-aac238cec9cab9efe7319d8397b95e7a77bdb5cd.tar.xz mv-aac238cec9cab9efe7319d8397b95e7a77bdb5cd.zip |
Fix perfomance issue with caching complex sprites.
-rw-r--r-- | src/animatedsprite.cpp | 11 | ||||
-rw-r--r-- | src/animatedsprite.h | 2 | ||||
-rw-r--r-- | src/compoundsprite.cpp | 147 | ||||
-rw-r--r-- | src/compoundsprite.h | 27 | ||||
-rw-r--r-- | src/resources/animation.cpp | 2 | ||||
-rw-r--r-- | src/sprite.h | 6 |
6 files changed, 178 insertions, 17 deletions
diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp index 0b9eb5ddd..41aabf60c 100644 --- a/src/animatedsprite.cpp +++ b/src/animatedsprite.cpp @@ -306,3 +306,14 @@ void AnimatedSprite::setAlpha(float alpha) if (mFrame && mFrame->image && mFrame->image->getAlpha() != mAlpha) mFrame->image->setAlpha(mAlpha); } + +void *AnimatedSprite::getHash() +{ + if (mFrame) + return mFrame; +// if (mFrame && mFrame->image) +// return mFrame->image; +// if (mAnimation) +// return mAnimation; + return this; +} diff --git a/src/animatedsprite.h b/src/animatedsprite.h index e10e0f338..2a2cfb8d8 100644 --- a/src/animatedsprite.h +++ b/src/animatedsprite.h @@ -82,6 +82,8 @@ class AnimatedSprite : public Sprite virtual void setAlpha(float alpha); + virtual void *getHash(); + private: bool updateCurrentAnimation(unsigned int dt); diff --git a/src/compoundsprite.cpp b/src/compoundsprite.cpp index f92358791..e391a6f87 100644 --- a/src/compoundsprite.cpp +++ b/src/compoundsprite.cpp @@ -27,6 +27,7 @@ #include "openglgraphics.h" #include "opengl1graphics.h" #endif +#include "localplayer.h" #include "map.h" #include "resources/image.h" @@ -40,7 +41,11 @@ #define BUFFER_WIDTH 100 #define BUFFER_HEIGHT 100 +static const unsigned cache_max_size = 10; +static const unsigned cache_clean_part = 3; + CompoundSprite::CompoundSprite(): + mCacheItem(0), mImage(0), mAlphaImage(0), mOffsetX(0), mOffsetY(0), @@ -57,9 +62,9 @@ CompoundSprite::~CompoundSprite() clear(); - delete mImage; +// delete mImage; mImage = 0; - delete mAlphaImage; +// delete mAlphaImage; mAlphaImage = 0; } @@ -111,7 +116,7 @@ bool CompoundSprite::update(int time) bool CompoundSprite::draw(Graphics* graphics, int posX, int posY) const { if (mNeedsRedraw) - redraw(); + updateImages(); if (mAlpha == 1.0f && mImage) { @@ -278,6 +283,10 @@ void CompoundSprite::clear() std::vector<Sprite*>::clear(); mNeedsRedraw = true; + delete_all(imagesCache); + imagesCache.clear(); + delete mCacheItem; + mCacheItem = 0; } void CompoundSprite::ensureSize(size_t layerCount) @@ -287,7 +296,6 @@ void CompoundSprite::ensureSize(size_t layerCount) return; resize(layerCount, NULL); - mNeedsRedraw = true; } /** @@ -322,17 +330,6 @@ unsigned int CompoundSprite::getFrameCount(unsigned int layer) void CompoundSprite::redraw() const { -#ifdef USE_OPENGL - // TODO OpenGL support - if (Image::mUseOpenGL) - { - mNeedsRedraw = false; - return; - } -#endif - - if (size() <= 1) - return; #if SDL_BYTEORDER == SDL_BIG_ENDIAN int rmask = 0xff000000; @@ -397,7 +394,6 @@ void CompoundSprite::redraw() const mAlphaImage = Image::load(surfaceA); SDL_FreeSurface(surfaceA); - mNeedsRedraw = false; } void CompoundSprite::setAlpha(float alpha) @@ -414,3 +410,122 @@ void CompoundSprite::setAlpha(float alpha) mAlpha = alpha; } } + +void CompoundSprite::updateImages() const +{ +#ifdef USE_OPENGL + if (Image::mUseOpenGL) + return; +#endif + + if (size() <= 3) + return; + + mNeedsRedraw = false; + + if (updateFromCache()) + return; + + redraw(); + + if (mImage) + initCurrentCacheItem(); +} + +bool CompoundSprite::updateFromCache() const +{ + ImagesCache::iterator it = imagesCache.begin(); + ImagesCache::iterator it_end = imagesCache.end(); +// static int hits = 0; +// static int miss = 0; + + if (mCacheItem && mCacheItem->image) + { + imagesCache.push_front(mCacheItem); + mCacheItem = 0; + if (imagesCache.size() > cache_max_size) + { + for (unsigned f = 0; f < cache_clean_part; f ++) + { + CompoundItem *item = imagesCache.back(); + imagesCache.pop_back(); + delete item; + } + } + } + +// logger->log("cache size: %d, hit %d, miss %d", +// (int)imagesCache.size(), hits, miss); + + for (it = imagesCache.begin(); it != it_end; ++ it) + { + CompoundItem *ic = *it; + if (ic && ic->data.size() == size()) + { + bool fail(false); + SpriteConstIterator it1 = begin(); + SpriteConstIterator it1_end = end(); + VectorPointers::iterator it2 = ic->data.begin(); + VectorPointers::iterator it2_end = ic->data.end(); + + for (; it1 != it1_end && it2 != it2_end; ++ it1, ++ it2) + { + void *ptr1 = 0; + void *ptr2 = 0; + if (*it1) + ptr1 = (*it1)->getHash(); + if (*it2) + ptr2 = *it2; + if (ptr1 != ptr2) + { + fail = true; + break; + } + } + if (!fail) + { +// hits ++; + mImage = (*it)->image; + mAlphaImage = (*it)->alphaImage; + imagesCache.erase(it); + mCacheItem = ic; + return true; + } + } + } + mImage = 0; + mAlphaImage = 0; +// miss++; + return false; +} + +void CompoundSprite::initCurrentCacheItem() const +{ + delete mCacheItem; + mCacheItem = new CompoundItem(); + mCacheItem->image = mImage; + mCacheItem->alphaImage = mAlphaImage; +// mCacheItem->alpha = mAlpha; + + SpriteConstIterator it, it_end; + for (it = begin(), it_end = end(); it != it_end; ++ it) + { + if (*it) + mCacheItem->data.push_back((*it)->getHash()); + else + mCacheItem->data.push_back(0); + } +} + +CompoundItem::CompoundItem() : +// alpha(1.0f), + image(0), + alphaImage(0) +{ +} + +CompoundItem::~CompoundItem() +{ + delete image; + delete alphaImage; +} diff --git a/src/compoundsprite.h b/src/compoundsprite.h index 834ccd835..0841bcfb8 100644 --- a/src/compoundsprite.h +++ b/src/compoundsprite.h @@ -24,10 +24,26 @@ #include "sprite.h" +#include <list> #include <vector> class Image; +typedef std::list <void*> VectorPointers; + +class CompoundItem +{ + public: + CompoundItem(); + + ~CompoundItem(); + +// float alpha; + VectorPointers data; + Image *image; + Image *alphaImage; +}; + class CompoundSprite : public Sprite, private std::vector<Sprite*> { public: @@ -101,9 +117,18 @@ public: virtual void setAlpha(float alpha); private: - void redraw() const; + void updateImages() const; + + bool updateFromCache() const; + + void initCurrentCacheItem() const; + + typedef std::list<CompoundItem*> ImagesCache; + mutable ImagesCache imagesCache; + mutable CompoundItem *mCacheItem; + mutable Image *mImage; mutable Image *mAlphaImage; diff --git a/src/resources/animation.cpp b/src/resources/animation.cpp index 915d7ef30..ea7f44199 100644 --- a/src/resources/animation.cpp +++ b/src/resources/animation.cpp @@ -22,6 +22,8 @@ #include "resources/animation.h" +#include "log.h" + #include "utils/dtor.h" #include "debug.h" diff --git a/src/sprite.h b/src/sprite.h index 9c6401dcb..20f38bef0 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -104,6 +104,12 @@ class Sprite */ virtual unsigned int getFrameCount() const = 0; + virtual void *getHash() + { return 0; } + + virtual void *getHash2() + { return this; } + protected: float mAlpha; /**< The alpha opacity used to draw */ }; |