summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2009-02-23 17:54:02 +0000
committerrubidium <rubidium@openttd.org>2009-02-23 17:54:02 +0000
commit3ba802e99524797571e69ba57b6a30a12b031b72 (patch)
tree52608fad0b8c58f9fc141f8ff4e5d203be54f7fc
parent0c1b8ea602de72a96573b7e3301589e8e3249ca1 (diff)
downloadopenttd-3ba802e99524797571e69ba57b6a30a12b031b72.tar.xz
(svn r15556) -Change: don't temporary malloc+free when encoding sprites, just reuse the same piece of allocated memory for each encoding.
-rw-r--r--src/blitter/8bpp_optimized.cpp8
-rw-r--r--src/core/alloc_type.hpp55
-rw-r--r--src/spritecache.cpp15
-rw-r--r--src/spriteloader/spriteloader.hpp11
4 files changed, 66 insertions, 23 deletions
diff --git a/src/blitter/8bpp_optimized.cpp b/src/blitter/8bpp_optimized.cpp
index 350715dc6..62fae35c8 100644
--- a/src/blitter/8bpp_optimized.cpp
+++ b/src/blitter/8bpp_optimized.cpp
@@ -113,7 +113,12 @@ Sprite *Blitter_8bppOptimized::Encode(SpriteLoader::Sprite *sprite, Blitter::All
/* We have no idea how much memory we really need, so just guess something */
memory *= 5;
- SpriteData *temp_dst = (SpriteData *)MallocT<byte>(memory);
+
+ /* Don't allocate memory each time, but just keep some
+ * memory around as this function is called quite often
+ * and the memory usage is quite low. */
+ static ReusableBuffer<byte> temp_buffer;
+ SpriteData *temp_dst = (SpriteData *)temp_buffer.Allocate(memory);
byte *dst = temp_dst->data;
/* Make the sprites per zoom-level */
@@ -195,7 +200,6 @@ Sprite *Blitter_8bppOptimized::Encode(SpriteLoader::Sprite *sprite, Blitter::All
dest_sprite->x_offs = sprite->x_offs;
dest_sprite->y_offs = sprite->y_offs;
memcpy(dest_sprite->data, temp_dst, size);
- free(temp_dst);
return dest_sprite;
}
diff --git a/src/core/alloc_type.hpp b/src/core/alloc_type.hpp
index a2bda93e4..887ba7237 100644
--- a/src/core/alloc_type.hpp
+++ b/src/core/alloc_type.hpp
@@ -71,6 +71,61 @@ struct SmallStackSafeStackAlloc {
};
/**
+ * A reusable buffer that can be used for places that temporary allocate
+ * a bit of memory and do that very often, or for places where static
+ * memory is allocated that might need to be reallocated sometimes.
+ *
+ * Every time Allocate or ZeroAllocate is called previous results of both
+ * functions will become invalid.
+ */
+template <typename T>
+class ReusableBuffer {
+private:
+ T *buffer; ///< The real data buffer
+ size_t count; ///< Number of T elements in the buffer
+
+public:
+ /** Create a new buffer */
+ ReusableBuffer() : buffer(NULL), count(0) {}
+ /** Clear the buffer */
+ ~ReusableBuffer() { free(this->buffer); }
+
+ /**
+ * Get buffer of at least count times T.
+ * @note the buffer might be bigger
+ * @note calling this function invalidates any previous buffers given
+ * @param count the minimum buffer size
+ * @return the buffer
+ */
+ T *Allocate(size_t count)
+ {
+ if (this->count < count) {
+ free(this->buffer);
+ this->buffer = MallocT<T>(count);
+ }
+ return this->buffer;
+ }
+
+ /**
+ * Get buffer of at least count times T with zeroed memory.
+ * @note the buffer might be bigger
+ * @note calling this function invalidates any previous buffers given
+ * @param count the minimum buffer size
+ * @return the buffer
+ */
+ T *ZeroAllocate(size_t count)
+ {
+ if (this->count < count) {
+ free(this->buffer);
+ this->buffer = CallocT<T>(count);
+ } else {
+ memset(this->buffer, 0, sizeof(T) * count);
+ }
+ return this->buffer;
+ }
+};
+
+/**
* Base class that provides memory initialization on dynamically created objects.
* All allocated memory will be zeroed.
*/
diff --git a/src/spritecache.cpp b/src/spritecache.cpp
index c5fa7f037..0e7bb9550 100644
--- a/src/spritecache.cpp
+++ b/src/spritecache.cpp
@@ -560,17 +560,4 @@ void GfxInitSpriteMem()
_compact_cache_counter = 0;
}
-void SpriteLoader::Sprite::AllocateData(size_t size)
-{
- if (Sprite::size < size) {
- Sprite::size = size;
- Sprite::mem = ReallocT<SpriteLoader::CommonPixel>(Sprite::mem, Sprite::size);
- }
-
- memset(Sprite::mem, 0, sizeof(SpriteLoader::CommonPixel) * size);
-
- this->data = Sprite::mem;
-
-}
-/* static */ SpriteLoader::CommonPixel *SpriteLoader::Sprite::mem = NULL;
-/* static */ size_t SpriteLoader::Sprite::size = 0;
+/* static */ ReusableBuffer<SpriteLoader::CommonPixel> SpriteLoader::Sprite::buffer;
diff --git a/src/spriteloader/spriteloader.hpp b/src/spriteloader/spriteloader.hpp
index 9b431fb4f..762831ae4 100644
--- a/src/spriteloader/spriteloader.hpp
+++ b/src/spriteloader/spriteloader.hpp
@@ -5,6 +5,8 @@
#ifndef SPRITELOADER_HPP
#define SPRITELOADER_HPP
+#include "../core/alloc_type.hpp"
+
class SpriteLoader {
public:
struct CommonPixel {
@@ -22,9 +24,6 @@ public:
* This to prevent thousands of malloc + frees just to load a sprite.
*/
struct Sprite {
- Sprite() : data(NULL) {}
- ~Sprite() { assert(this->data == NULL || this->data == Sprite::mem); }
-
uint16 height; ///< Height of the sprite
uint16 width; ///< Width of the sprite
int16 x_offs; ///< The x-offset of where the sprite will be drawn
@@ -35,12 +34,10 @@ public:
* Allocate the sprite data of this sprite.
* @param size the minimum size of the data field.
*/
- void AllocateData(size_t size);
+ void AllocateData(size_t size) { this->data = Sprite::buffer.ZeroAllocate(size); }
private:
/** Allocated memory to pass sprite data around */
- static SpriteLoader::CommonPixel *mem;
- /** Size (in items) of the above memory. */
- static size_t size;
+ static ReusableBuffer<SpriteLoader::CommonPixel> buffer;
};
/**