summaryrefslogtreecommitdiff
path: root/src/resources/image.cpp
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2010-10-12 19:59:25 +0300
committerAndrei Karas <akaras@inbox.ru>2010-10-16 20:44:37 +0300
commit0d3d7c908ef6d294b14f55f09c9d83767fbc5f32 (patch)
tree35a175491e6d08cdbd79ab6c9de7e13560132236 /src/resources/image.cpp
parentbdf409c9c4ce083881133879947cc0a6c2cce0f1 (diff)
downloadmana-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/image.cpp')
-rw-r--r--src/resources/image.cpp94
1 files changed, 87 insertions, 7 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