All pastes #1960291 Raw Edit

Stuff

public diff v1 · immutable
#1960291 ·published 2010-10-12 18:21 UTC
rendered paste body
From 3b04d0defc80c1a5aedddfd93d8d79493d7ec65e Mon Sep 17 00:00:00 2001From: Andrei Karas <akaras@inbox.ru>Date: Tue, 12 Oct 2010 19:59:25 +0300Subject: [PATCH] Impliment opacity cache for SDL surfaces.Enabled by default.Can be disabled in configuration option "alphaCache" if set it to 0.--- src/client.cpp                    |    2 + src/gui/gui.cpp                   |    3 + src/resources/image.cpp           |   90 ++++++++++++++++++++++++++++++++++--- src/resources/image.h             |   25 +++++++++- src/resources/resourcemanager.cpp |   15 ++++++ src/resources/resourcemanager.h   |    6 +++ 6 files changed, 131 insertions(+), 10 deletions(-)diff --git a/src/client.cpp b/src/client.cppindex f1b363e..e4203af 100644--- a/src/client.cpp+++ b/src/client.cpp@@ -251,6 +251,8 @@ Client::Client(const Options &options):                                 "Exiting.", mLocalDataDir.c_str()));     } +    Image::setEnableAlphaCache(config.getValue("alphaCache", true));+ #if defined __APPLE__     CFBundleRef mainBundle = CFBundleGetMainBundle();     CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);diff --git a/src/gui/gui.cpp b/src/gui/gui.cppindex df2ddad..75f6743 100644--- a/src/gui/gui.cpp+++ b/src/gui/gui.cpp@@ -160,6 +160,9 @@ Gui::~Gui()  void Gui::logic() {+    ResourceManager *resman = ResourceManager::getInstance();+    resman->clearScheduled();+     // Fade out mouse cursor after extended inactivity     if (mMouseInactivityTimer < 100 * 15)     {diff --git a/src/resources/image.cpp b/src/resources/image.cppindex 82799bc..9996330 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@@ -371,6 +424,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 +621,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_OPENGLdiff --git a/src/resources/image.h b/src/resources/image.hindex 3e8ad55..815b776 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.cppindex c63b626..00e4726 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.hindex 28ab472..870182e 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;-- 1.7.2.3