diff options
Diffstat (limited to 'src/resources')
-rw-r--r-- | src/resources/ambientlayer.cpp | 10 | ||||
-rw-r--r-- | src/resources/image.cpp | 49 | ||||
-rw-r--r-- | src/resources/image.h | 9 | ||||
-rw-r--r-- | src/resources/resource.cpp | 25 | ||||
-rw-r--r-- | src/resources/resource.h | 23 | ||||
-rw-r--r-- | src/resources/resourcemanager.cpp | 28 | ||||
-rw-r--r-- | src/resources/resourcemanager.h | 27 |
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); |