mirror of https://github.com/OpenTTD/OpenTTD
(svn r15556) -Change: don't temporary malloc+free when encoding sprites, just reuse the same piece of allocated memory for each encoding.
parent
0c1b8ea602
commit
3ba802e995
|
@ -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 */
|
/* We have no idea how much memory we really need, so just guess something */
|
||||||
memory *= 5;
|
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;
|
byte *dst = temp_dst->data;
|
||||||
|
|
||||||
/* Make the sprites per zoom-level */
|
/* 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->x_offs = sprite->x_offs;
|
||||||
dest_sprite->y_offs = sprite->y_offs;
|
dest_sprite->y_offs = sprite->y_offs;
|
||||||
memcpy(dest_sprite->data, temp_dst, size);
|
memcpy(dest_sprite->data, temp_dst, size);
|
||||||
free(temp_dst);
|
|
||||||
|
|
||||||
return dest_sprite;
|
return dest_sprite;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,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.
|
* Base class that provides memory initialization on dynamically created objects.
|
||||||
* All allocated memory will be zeroed.
|
* All allocated memory will be zeroed.
|
||||||
|
|
|
@ -560,17 +560,4 @@ void GfxInitSpriteMem()
|
||||||
_compact_cache_counter = 0;
|
_compact_cache_counter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteLoader::Sprite::AllocateData(size_t size)
|
/* static */ ReusableBuffer<SpriteLoader::CommonPixel> SpriteLoader::Sprite::buffer;
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#ifndef SPRITELOADER_HPP
|
#ifndef SPRITELOADER_HPP
|
||||||
#define SPRITELOADER_HPP
|
#define SPRITELOADER_HPP
|
||||||
|
|
||||||
|
#include "../core/alloc_type.hpp"
|
||||||
|
|
||||||
class SpriteLoader {
|
class SpriteLoader {
|
||||||
public:
|
public:
|
||||||
struct CommonPixel {
|
struct CommonPixel {
|
||||||
|
@ -22,9 +24,6 @@ public:
|
||||||
* This to prevent thousands of malloc + frees just to load a sprite.
|
* This to prevent thousands of malloc + frees just to load a sprite.
|
||||||
*/
|
*/
|
||||||
struct Sprite {
|
struct Sprite {
|
||||||
Sprite() : data(NULL) {}
|
|
||||||
~Sprite() { assert(this->data == NULL || this->data == Sprite::mem); }
|
|
||||||
|
|
||||||
uint16 height; ///< Height of the sprite
|
uint16 height; ///< Height of the sprite
|
||||||
uint16 width; ///< Width of the sprite
|
uint16 width; ///< Width of the sprite
|
||||||
int16 x_offs; ///< The x-offset of where the sprite will be drawn
|
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.
|
* Allocate the sprite data of this sprite.
|
||||||
* @param size the minimum size of the data field.
|
* @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:
|
private:
|
||||||
/** Allocated memory to pass sprite data around */
|
/** Allocated memory to pass sprite data around */
|
||||||
static SpriteLoader::CommonPixel *mem;
|
static ReusableBuffer<SpriteLoader::CommonPixel> buffer;
|
||||||
/** Size (in items) of the above memory. */
|
|
||||||
static size_t size;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue