diff options
author | Andrei Karas <akaras@inbox.ru> | 2010-10-12 19:59:25 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2010-10-16 20:44:37 +0300 |
commit | 0d3d7c908ef6d294b14f55f09c9d83767fbc5f32 (patch) | |
tree | 35a175491e6d08cdbd79ab6c9de7e13560132236 /src/resources | |
parent | bdf409c9c4ce083881133879947cc0a6c2cce0f1 (diff) | |
download | mana-0d3d7c908ef6d294b14f55f09c9d83767fbc5f32.tar.gz mana-0d3d7c908ef6d294b14f55f09c9d83767fbc5f32.tar.bz2 mana-0d3d7c908ef6d294b14f55f09c9d83767fbc5f32.tar.xz mana-0d3d7c908ef6d294b14f55f09c9d83767fbc5f32.zip |
Implement opacity cache for SDL surfaces.
Enabled by default.
Can be disabled in configuration option "alphaCache" if set it to 0.
Reviewed-by: Bertram
Diffstat (limited to 'src/resources')
-rw-r--r-- | src/resources/image.cpp | 94 | ||||
-rw-r--r-- | src/resources/image.h | 25 | ||||
-rw-r--r-- | src/resources/resourcemanager.cpp | 15 | ||||
-rw-r--r-- | src/resources/resourcemanager.h | 6 |
4 files changed, 130 insertions, 10 deletions
diff --git a/src/resources/image.cpp b/src/resources/image.cpp index 82799bce..cd6bda15 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -22,6 +22,7 @@ #include "resources/image.h" #include "resources/dye.h" +#include "resources/resourcemanager.h" #ifdef USE_OPENGL #include "openglgraphics.h" @@ -37,6 +38,7 @@ bool Image::mUseOpenGL = false; int Image::mTextureType = 0; int Image::mTextureSize = 0; #endif +bool Image::mEnableAlphaCache = false; Image::Image(SDL_Surface *image, bool hasAlphaChannel, Uint8 *alphaChannel): mAlpha(1.0f), @@ -48,6 +50,8 @@ Image::Image(SDL_Surface *image, bool hasAlphaChannel, Uint8 *alphaChannel): mGLImage = 0; #endif + mUseAlphaCache = Image::mEnableAlphaCache; + mBounds.x = 0; mBounds.y = 0; @@ -71,6 +75,7 @@ Image::Image(GLuint glimage, int width, int height, int texWidth, int texHeight) mHasAlphaChannel(true), mSDLSurface(0), mAlphaChannel(0), + mUseAlphaCache(false), mGLImage(glimage), mTexWidth(texWidth), mTexHeight(texHeight) @@ -166,12 +171,28 @@ Image *Image::load(SDL_Surface *tmpImage) return _SDLload(tmpImage); } +void Image::cleanCache() +{ + ResourceManager *resman = ResourceManager::getInstance(); + + for (std::map<float, SDL_Surface*>::iterator + i = mAlphaCache.begin(), i_end = mAlphaCache.end(); + i != i_end; ++i) + { + if (mSDLSurface != i->second) + resman->scheduleDelete(i->second); + i->second = 0; + } + mAlphaCache.clear(); +} + void Image::unload() { mLoaded = false; if (mSDLSurface) { + cleanCache(); // Free the image surface. SDL_FreeSurface(mSDLSurface); mSDLSurface = NULL; @@ -211,6 +232,14 @@ bool Image::hasAlphaChannel() return false; } +SDL_Surface *Image::getByAlpha(float alpha) +{ + std::map<float, SDL_Surface*>::iterator it = mAlphaCache.find(alpha); + if (it != mAlphaCache.end()) + return (*it).second; + return 0; +} + void Image::setAlpha(float alpha) { if (mAlpha == alpha) @@ -219,10 +248,34 @@ void Image::setAlpha(float alpha) if (alpha < 0.0f || alpha > 1.0f) return; - mAlpha = alpha; - if (mSDLSurface) { + if (mUseAlphaCache) + { + SDL_Surface *surface = getByAlpha(mAlpha); + if (!surface) + { + if (mAlphaCache.size() > 100) + cleanCache(); + + mAlphaCache[mAlpha] = mSDLSurface; + } + surface = getByAlpha(alpha); + if (surface) + { + mAlphaCache.erase(alpha); + mSDLSurface = surface; + mAlpha = alpha; + return; + } + else + { + mSDLSurface = Image::duplicateSurface(mSDLSurface); + } + } + + mAlpha = alpha; + if (!hasAlphaChannel()) { // Set the alpha value this image is drawn at @@ -263,6 +316,10 @@ void Image::setAlpha(float alpha) SDL_UnlockSurface(mSDLSurface); } } + else + { + mAlpha = alpha; + } } Image* Image::SDLmerge(Image *image, int x, int y) @@ -371,6 +428,14 @@ Image* Image::SDLgetScaledImage(int width, int height) return scaledImage; } +SDL_Surface* Image::duplicateSurface(SDL_Surface* tmpImage) +{ + if (!tmpImage || !tmpImage->format) + return NULL; + + return SDL_ConvertSurface(tmpImage, tmpImage->format, SDL_SWSURFACE); +} + Image *Image::_SDLload(SDL_Surface *tmpImage) { if (!tmpImage) @@ -560,25 +625,40 @@ Image *Image::getSubImage(int x, int y, int width, int height) return new SubImage(this, mSDLSurface, x, y, width, height); } +void Image::terminateAlphaCache() +{ + cleanCache(); + mUseAlphaCache = false; +} + //============================================================================ // SubImage Class //============================================================================ SubImage::SubImage(Image *parent, SDL_Surface *image, - int x, int y, int width, int height): + int x, int y, int width, int height): Image(image), mParent(parent) { - mParent->incRef(); - - mHasAlphaChannel = mParent->hasAlphaChannel(); - mAlphaChannel = mParent->SDLgetAlphaChannel(); + if (mParent) + { + mParent->incRef(); + mParent->terminateAlphaCache(); + mHasAlphaChannel = mParent->hasAlphaChannel(); + mAlphaChannel = mParent->SDLgetAlphaChannel(); + } + else + { + mHasAlphaChannel = false; + mAlphaChannel = 0; + } // Set up the rectangle. mBounds.x = x; mBounds.y = y; mBounds.w = width; mBounds.h = height; + mUseAlphaCache = false; } #ifdef USE_OPENGL diff --git a/src/resources/image.h b/src/resources/image.h index 3e8ad551..815b7764 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -39,6 +39,8 @@ #include <SDL_opengl.h> #endif +#include <map> + class Dye; class Position; @@ -169,6 +171,15 @@ class Image : public Resource Uint8 *SDLgetAlphaChannel() const { return mAlphaChannel; } + SDL_Surface* duplicateSurface(SDL_Surface* tmpImage); + + void cleanCache(); + + void terminateAlphaCache(); + + static void setEnableAlphaCache(bool n) + { mEnableAlphaCache = n; } + #ifdef USE_OPENGL // OpenGL only public functions @@ -208,14 +219,22 @@ class Image : public Resource /** SDL_Surface to SDL_Surface Image loader */ static Image *_SDLload(SDL_Surface *tmpImage); + SDL_Surface *getByAlpha(float alpha); + SDL_Surface *mSDLSurface; /** Alpha Channel pointer used for 32bit based SDL surfaces */ Uint8 *mAlphaChannel; - // ----------------------- - // OpenGL protected members - // ----------------------- + std::map<float, SDL_Surface*> mAlphaCache; + + bool mUseAlphaCache; + + static bool mEnableAlphaCache; + + // ----------------------- + // OpenGL protected members + // ----------------------- #ifdef USE_OPENGL /** * OpenGL Constructor. diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index c63b626e..00e4726e 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -533,3 +533,18 @@ SDL_Surface *ResourceManager::loadSDLSurface(const std::string &filename) return tmp; } + +void ResourceManager::scheduleDelete(SDL_Surface* surface) +{ + mDeletedSurfaces.insert(surface); +} + +void ResourceManager::clearScheduled() +{ + for (std::set<SDL_Surface*>::iterator i = mDeletedSurfaces.begin(), + i_end = mDeletedSurfaces.end(); i != i_end; ++i) + { + SDL_FreeSurface(*i); + } + mDeletedSurfaces.clear(); +} diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h index 28ab4725..870182e4 100644 --- a/src/resources/resourcemanager.h +++ b/src/resources/resourcemanager.h @@ -26,6 +26,7 @@ #include <map> #include <string> #include <vector> +#include <set> class Image; class ImageSet; @@ -205,6 +206,10 @@ class ResourceManager */ SDL_Surface *loadSDLSurface(const std::string &filename); + void scheduleDelete(SDL_Surface* surface); + + void clearScheduled(); + /** * Returns an instance of the class, creating one if it does not * already exist. @@ -227,6 +232,7 @@ class ResourceManager static ResourceManager *instance; typedef std::map<std::string, Resource*> Resources; typedef Resources::iterator ResourceIterator; + std::set<SDL_Surface*> mDeletedSurfaces; Resources mResources; Resources mOrphanedResources; time_t mOldestOrphan; |