summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2011-08-01 21:05:48 +0300
committerAndrei Karas <akaras@inbox.ru>2011-08-02 18:38:14 +0300
commitaac238cec9cab9efe7319d8397b95e7a77bdb5cd (patch)
tree3298f3b604d4d45cc6d04f871f6a1abb29cdd554
parent4e7096f15eba73e6ea28066df6ab389aab3f052c (diff)
downloadmanaplus-aac238cec9cab9efe7319d8397b95e7a77bdb5cd.tar.gz
manaplus-aac238cec9cab9efe7319d8397b95e7a77bdb5cd.tar.bz2
manaplus-aac238cec9cab9efe7319d8397b95e7a77bdb5cd.tar.xz
manaplus-aac238cec9cab9efe7319d8397b95e7a77bdb5cd.zip
Fix perfomance issue with caching complex sprites.
-rw-r--r--src/animatedsprite.cpp11
-rw-r--r--src/animatedsprite.h2
-rw-r--r--src/compoundsprite.cpp147
-rw-r--r--src/compoundsprite.h27
-rw-r--r--src/resources/animation.cpp2
-rw-r--r--src/sprite.h6
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 */
};