From 0d3d7c908ef6d294b14f55f09c9d83767fbc5f32 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Tue, 12 Oct 2010 19:59:25 +0300 Subject: Implement opacity cache for SDL surfaces. Enabled by default. Can be disabled in configuration option "alphaCache" if set it to 0. Reviewed-by: Bertram --- src/resources/image.cpp | 94 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 87 insertions(+), 7 deletions(-) (limited to 'src/resources/image.cpp') 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::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::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 -- cgit v1.2.3-60-g2f50