summaryrefslogtreecommitdiff
path: root/src/resources
diff options
context:
space:
mode:
Diffstat (limited to 'src/resources')
-rw-r--r--src/resources/ambientlayer.cpp10
-rw-r--r--src/resources/image.cpp49
-rw-r--r--src/resources/image.h9
-rw-r--r--src/resources/resource.cpp25
-rw-r--r--src/resources/resource.h23
-rw-r--r--src/resources/resourcemanager.cpp28
-rw-r--r--src/resources/resourcemanager.h27
7 files changed, 115 insertions, 56 deletions
diff --git a/src/resources/ambientlayer.cpp b/src/resources/ambientlayer.cpp
index d1fc93d3..c31afbac 100644
--- a/src/resources/ambientlayer.cpp
+++ b/src/resources/ambientlayer.cpp
@@ -32,6 +32,7 @@ AmbientLayer::AmbientLayer(Image *img, float parallax,
mSpeedX(speedX), mSpeedY(speedY),
mKeepRatio(keepRatio)
{
+ mImage->incRef();
if (keepRatio && !mImage->useOpenGL()
&& defaultScreenWidth != 0
@@ -47,17 +48,10 @@ AmbientLayer::AmbientLayer(Image *img, float parallax,
if (rescaledOverlay)
{
- // Replace the resource with the new one...
- std::string idPath = mImage->getIdPath() + "_rescaled";
- ResourceManager::getInstance()->addResource(idPath, rescaledOverlay);
+ mImage->decRef();
mImage = rescaledOverlay;
- rescaledOverlay->incRef();
}
- else
- mImage->incRef();
}
- else
- mImage->incRef();
}
AmbientLayer::~AmbientLayer()
diff --git a/src/resources/image.cpp b/src/resources/image.cpp
index 3a6f7236..975bd647 100644
--- a/src/resources/image.cpp
+++ b/src/resources/image.cpp
@@ -326,31 +326,52 @@ void Image::setAlpha(float alpha)
}
}
-Image* Image::SDLgetScaledImage(int width, int height)
+Image *Image::SDLgetScaledImage(int width, int height)
{
- // No scaling on incorrect new values.
if (width == 0 || height == 0)
- return NULL;
+ return 0;
- // No scaling when there is ... no different given size ...
+ // Increase our reference count and return ourselves in case of same size
if (width == getWidth() && height == getHeight())
- return NULL;
+ {
+ incRef();
+ return this;
+ }
- Image* scaledImage = NULL;
- SDL_Surface* scaledSurface = NULL;
+ if (!mSDLSurface)
+ return 0;
- if (mSDLSurface)
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ // Generate a unique ID path for storing the scaled version in the
+ // resource manager.
+ std::string idPath = getIdPath();
+ idPath += ":scaled:";
+ idPath += toString(width);
+ idPath += "x";
+ idPath += toString(height);
+
+ // Try whether a scaled version is already available
+ Image *scaledImage = static_cast<Image*>(resman->get(idPath));
+
+ if (!scaledImage)
{
- scaledSurface = zoomSurface(mSDLSurface,
- (double) width / getWidth(),
- (double) height / getHeight(),
- 1);
+ // No scaled version with this size exists already, so create one
+ SDL_Surface *scaledSurface = zoomSurface(mSDLSurface,
+ (double) width / getWidth(),
+ (double) height / getHeight(),
+ 1);
- // The load function takes care of the SDL<->OpenGL implementation
- // and about freeing the given SDL_surface*.
if (scaledSurface)
+ {
scaledImage = load(scaledSurface);
+ SDL_FreeSurface(scaledSurface);
+
+ // Place the scaled image in the resource manager
+ resman->addResource(idPath, scaledImage);
+ }
}
+
return scaledImage;
}
diff --git a/src/resources/image.h b/src/resources/image.h
index b826112d..7df74c3f 100644
--- a/src/resources/image.h
+++ b/src/resources/image.h
@@ -147,14 +147,15 @@ class Image : public Resource
{ return mDisableTransparency; }
/**
- * Gets an scaled instance of an image.
+ * Gets an scaled instance of an image. The returned image is managed
+ * by the ResourceManager.
*
- * @param width The desired width of the scaled image.
+ * @param width The desired width of the scaled image.
* @param height The desired height of the scaled image.
*
- * @return A new Image* object.
+ * @return An Image resource, or 0 on failure.
*/
- Image* SDLgetScaledImage(int width, int height);
+ Image *SDLgetScaledImage(int width, int height);
/**
* Get the alpha Channel of a SDL surface.
diff --git a/src/resources/resource.cpp b/src/resources/resource.cpp
index 4f6a2519..cdff8060 100644
--- a/src/resources/resource.cpp
+++ b/src/resources/resource.cpp
@@ -27,16 +27,7 @@
#include <cassert>
-Resource::~Resource()
-{
-}
-
-void Resource::incRef()
-{
- ++mRefCount;
-}
-
-void Resource::decRef()
+void Resource::decRef(OrphanPolicy orphanPolicy)
{
// Reference may not already have reached zero
if (mRefCount == 0) {
@@ -48,8 +39,18 @@ void Resource::decRef()
if (mRefCount == 0)
{
- // Warn the manager that this resource is no longer used.
ResourceManager *resman = ResourceManager::getInstance();
- resman->release(this);
+
+ switch (orphanPolicy)
+ {
+ case DeleteLater:
+ default:
+ resman->release(this);
+ break;
+ case DeleteImmediately:
+ resman->remove(this);
+ delete this;
+ break;
+ }
}
}
diff --git a/src/resources/resource.h b/src/resources/resource.h
index 53b05ee8..af688eb0 100644
--- a/src/resources/resource.h
+++ b/src/resources/resource.h
@@ -33,21 +33,26 @@ class Resource
friend class ResourceManager;
public:
- Resource(): mRefCount(0) {}
+ enum OrphanPolicy {
+ DeleteLater,
+ DeleteImmediately
+ };
+
+ Resource():
+ mRefCount(0)
+ {}
/**
* Increments the internal reference count.
*/
- void incRef();
+ void incRef() { ++mRefCount; }
/**
- * Decrements the reference count and deletes the object
- * if no references are left.
- *
- * @return <code>true</code> if the object was deleted
- * <code>false</code> otherwise.
+ * Decrements the reference count. When no references are left, either
+ * schedules the object for deletion or deletes it immediately,
+ * depending on the \a orphanPolicy.
*/
- void decRef();
+ void decRef(OrphanPolicy orphanPolicy = DeleteLater);
/**
* Return the path identifying this resource.
@@ -56,7 +61,7 @@ class Resource
{ return mIdPath; }
protected:
- virtual ~Resource();
+ virtual ~Resource() {}
private:
std::string mIdPath; /**< Path identifying this resource. */
diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp
index 15d7c8eb..a9e7e565 100644
--- a/src/resources/resourcemanager.cpp
+++ b/src/resources/resourcemanager.cpp
@@ -117,9 +117,11 @@ void ResourceManager::cleanOrphans()
timeval tv;
gettimeofday(&tv, NULL);
// Delete orphaned resources after 30 seconds.
- time_t oldest = tv.tv_sec, threshold = oldest - 30;
+ time_t oldest = tv.tv_sec;
+ time_t threshold = oldest - 30;
- if (mOrphanedResources.empty() || mOldestOrphan >= threshold) return;
+ if (mOrphanedResources.empty() || mOldestOrphan >= threshold)
+ return;
ResourceIterator iter = mOrphanedResources.begin();
while (iter != mOrphanedResources.end())
@@ -128,7 +130,8 @@ void ResourceManager::cleanOrphans()
time_t t = res->mTimeStamp;
if (t >= threshold)
{
- if (t < oldest) oldest = t;
+ if (t < oldest)
+ oldest = t;
++iter;
}
else
@@ -234,6 +237,17 @@ bool ResourceManager::addResource(const std::string &idPath,
return false;
}
+Resource *ResourceManager::get(const std::string &idPath)
+{
+ ResourceIterator resIter = mResources.find(idPath);
+ if (resIter != mResources.end())
+ {
+ resIter->second->incRef();
+ return resIter->second;
+ }
+ return 0;
+}
+
Resource *ResourceManager::get(const std::string &idPath, generator fun,
void *data)
{
@@ -392,12 +406,18 @@ void ResourceManager::release(Resource *res)
time_t timestamp = tv.tv_sec;
res->mTimeStamp = timestamp;
- if (mOrphanedResources.empty()) mOldestOrphan = timestamp;
+ if (mOrphanedResources.empty())
+ mOldestOrphan = timestamp;
mOrphanedResources.insert(*resIter);
mResources.erase(resIter);
}
+void ResourceManager::remove(Resource *res)
+{
+ mResources.erase(res->mIdPath);
+}
+
ResourceManager *ResourceManager::getInstance()
{
// Create a new instance if necessary.
diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h
index 5295be5c..5abc81e2 100644
--- a/src/resources/resourcemanager.h
+++ b/src/resources/resourcemanager.h
@@ -107,6 +107,16 @@ class ResourceManager
std::string getPath(const std::string &file);
/**
+ * Returns the resource with the specified idPath, or 0 when no such
+ * resource is available. Increments the reference count.
+ *
+ * @param idPath The resource identifier path.
+ * @return A valid resource or <code>NULL</code> if the resource could
+ * not be found.
+ */
+ Resource *get(const std::string &idPath);
+
+ /**
* Creates a resource and adds it to the resource map.
*
* @param idPath The resource identifier path.
@@ -178,11 +188,6 @@ class ResourceManager
SpriteDef *getSprite(const std::string &path, int variant = 0);
/**
- * Releases a resource, placing it in the set of orphaned resources.
- */
- void release(Resource *);
-
- /**
* Allocates data into a buffer pointer for raw data loading. The
* returned data is expected to be freed using <code>free()</code>.
*
@@ -225,6 +230,18 @@ class ResourceManager
private:
/**
+ * Releases a resource, placing it in the set of orphaned resources.
+ * Only called from Resource::decRef,
+ */
+ void release(Resource *);
+
+ /**
+ * Removes a resource from the list of resources managed by the
+ * resource manager. Only called from Resource::decRef,
+ */
+ void remove(Resource *);
+
+ /**
* Deletes the resource after logging a cleanup message.
*/
static void cleanUp(Resource *resource);