Sprite cache: Allow caching only required subset of sprite zoom levels

Enable for blitters based on 32bpp_optimized or SSE
This commit is contained in:
Jonathan G Rennison
2023-08-22 22:16:04 +01:00
parent 785216db73
commit 46f5fb9f25
28 changed files with 423 additions and 172 deletions

View File

@@ -210,7 +210,6 @@ inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
}
break;
case BM_BLACK_REMAP:
memset_colour(dst, _black_colour, n);
memset(anim, 0, n * sizeof(*anim));

View File

@@ -36,6 +36,12 @@ class Blitter_32bppSSE4_Anim FINAL : public Blitter_32bppSSE2_Anim, public Blitt
private:
public:
Blitter_32bppSSE4_Anim()
{
this->Blitter_32bppSSE2_Anim::SetSupportsMissingZoomLevels(true);
this->Blitter_32bppSSE4::SetSupportsMissingZoomLevels(true);
}
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent, bool animated>
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;

View File

@@ -301,6 +301,7 @@ template <bool Tpal_to_rgb> Sprite *Blitter_32bppOptimized::EncodeInternal(const
ZoomLevel zoom_min;
ZoomLevel zoom_max;
uint8 missing_zoom_levels = 0;
if (sprite->type == SpriteType::Font) {
zoom_min = ZOOM_LVL_NORMAL;
@@ -317,6 +318,7 @@ template <bool Tpal_to_rgb> Sprite *Blitter_32bppOptimized::EncodeInternal(const
uint n_size = 0;
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
const SpriteLoader::Sprite *src_orig = &sprite[z];
if (src_orig->data == nullptr) continue;
uint size = src_orig->height * src_orig->width;
@@ -339,6 +341,13 @@ template <bool Tpal_to_rgb> Sprite *Blitter_32bppOptimized::EncodeInternal(const
const SpriteLoader::CommonPixel *src = (const SpriteLoader::CommonPixel *)src_orig->data;
if (src == nullptr) {
lengths[z][0] = 0;
lengths[z][1] = 0;
SetBit(missing_zoom_levels, z);
continue;
}
for (uint y = src_orig->height; y > 0; y--) {
/* Index 0 of dst_px and dst_n is left as space to save the length of the row to be filled later. */
Colour *dst_px = (Colour *)&dst_px_ln[1];
@@ -448,24 +457,34 @@ template <bool Tpal_to_rgb> Sprite *Blitter_32bppOptimized::EncodeInternal(const
len += lengths[z][0] + lengths[z][1];
}
Sprite *dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite) + sizeof(SpriteData) + len);
Sprite *dest_sprite = (Sprite *)allocator(sizeof(Sprite) + sizeof(SpriteData) + len);
if (len == 0) {
/* Mark sprite as having no levels at all, and therefore replaceable */
missing_zoom_levels = UINT8_MAX;
}
dest_sprite->height = sprite->height;
dest_sprite->width = sprite->width;
dest_sprite->x_offs = sprite->x_offs;
dest_sprite->y_offs = sprite->y_offs;
dest_sprite->next = nullptr;
dest_sprite->missing_zoom_levels = missing_zoom_levels;
SpriteData *dst = (SpriteData *)dest_sprite->data;
memset(dst, 0, sizeof(*dst));
/* Store sprite flags. */
dst->flags = flags;
uint32 next_offset = 0;
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
dst->offset[z][0] = z == zoom_min ? 0 : lengths[z - 1][1] + dst->offset[z - 1][1];
dst->offset[z][1] = lengths[z][0] + dst->offset[z][0];
dst->offset[z][0] = next_offset;
dst->offset[z][1] = lengths[z][0] + next_offset;
memcpy(dst->data + dst->offset[z][0], dst_px_orig[z], lengths[z][0]);
memcpy(dst->data + dst->offset[z][1], dst_n_orig[z], lengths[z][1]);
next_offset += lengths[z][0] + lengths[z][1];
if (lengths[z][0] != 0) memcpy(dst->data + dst->offset[z][0], dst_px_orig[z], lengths[z][0]);
if (lengths[z][1] != 0) memcpy(dst->data + dst->offset[z][1], dst_n_orig[z], lengths[z][1]);
}
free(px_buffer);

View File

@@ -22,6 +22,11 @@ public:
byte data[]; ///< Data, all zoomlevels.
};
Blitter_32bppOptimized()
{
this->SetSupportsMissingZoomLevels(true);
}
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
Sprite *Encode(const SpriteLoader::Sprite *sprite, AllocatorProc *allocator) override;

View File

@@ -137,6 +137,8 @@ Sprite *Blitter_32bppSimple::Encode(const SpriteLoader::Sprite *sprite, Allocato
dest_sprite->width = sprite->width;
dest_sprite->x_offs = sprite->x_offs;
dest_sprite->y_offs = sprite->y_offs;
dest_sprite->next = nullptr;
dest_sprite->missing_zoom_levels = 0;
dst = (Blitter_32bppSimple::Pixel *)dest_sprite->data;
SpriteLoader::CommonPixel *src = (SpriteLoader::CommonPixel *)sprite->data;

View File

@@ -28,6 +28,7 @@ Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::Sprite *sprite, Alloca
*/
ZoomLevel zoom_min = ZOOM_LVL_NORMAL;
ZoomLevel zoom_max = ZOOM_LVL_NORMAL;
uint8 missing_zoom_levels = 0;
if (sprite->type != SpriteType::Font) {
zoom_min = _settings_client.gui.zoom_min;
zoom_max = (ZoomLevel) std::min(_settings_client.gui.zoom_max, ZOOM_LVL_DRAW_SPR);
@@ -40,6 +41,15 @@ Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::Sprite *sprite, Alloca
uint all_sprites_size = 0;
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
const SpriteLoader::Sprite *src_sprite = &sprite[z];
if (src_sprite->data == nullptr) {
sd.infos[z].sprite_offset = 0;
sd.infos[z].mv_offset = 0;
sd.infos[z].sprite_line_size = 0;
sd.infos[z].sprite_width = 0;
SetBit(missing_zoom_levels, z);
continue;
}
sd.infos[z].sprite_width = src_sprite->width;
sd.infos[z].sprite_offset = all_sprites_size;
sd.infos[z].sprite_line_size = sizeof(Colour) * src_sprite->width + sizeof(uint32) * META_LENGTH;
@@ -56,6 +66,8 @@ Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::Sprite *sprite, Alloca
dst_sprite->width = sprite->width;
dst_sprite->x_offs = sprite->x_offs;
dst_sprite->y_offs = sprite->y_offs;
dst_sprite->next = nullptr;
dst_sprite->missing_zoom_levels = missing_zoom_levels;
memcpy(dst_sprite->data, &sd, sizeof(SpriteData));
/* Copy colours and determine flags. */
@@ -64,6 +76,9 @@ Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::Sprite *sprite, Alloca
bool has_translucency = false;
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
const SpriteLoader::Sprite *src_sprite = &sprite[z];
if (src_sprite->data == nullptr) {
continue;
}
const SpriteLoader::CommonPixel *src = (const SpriteLoader::CommonPixel *) src_sprite->data;
Colour *dst_rgba_line = (Colour *) &dst_sprite->data[sizeof(SpriteData) + sd.infos[z].sprite_offset];
MapValue *dst_mv = (MapValue *) &dst_sprite->data[sizeof(SpriteData) + sd.infos[z].mv_offset];

View File

@@ -70,6 +70,11 @@ public:
/** The SSE2 32 bpp blitter (without palette animation). */
class Blitter_32bppSSE2 : public Blitter_32bppSimple, public Blitter_32bppSSE_Base {
public:
Blitter_32bppSSE2()
{
this->SetSupportsMissingZoomLevels(true);
}
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent>
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);

View File

@@ -225,6 +225,8 @@ Sprite *Blitter_8bppOptimized::Encode(const SpriteLoader::Sprite *sprite, Alloca
dest_sprite->width = sprite->width;
dest_sprite->x_offs = sprite->x_offs;
dest_sprite->y_offs = sprite->y_offs;
dest_sprite->next = nullptr;
dest_sprite->missing_zoom_levels = 0;
memcpy(dest_sprite->data, temp_dst, size);
return dest_sprite;

View File

@@ -70,6 +70,8 @@ Sprite *Blitter_8bppSimple::Encode(const SpriteLoader::Sprite *sprite, Allocator
dest_sprite->width = sprite->width;
dest_sprite->x_offs = sprite->x_offs;
dest_sprite->y_offs = sprite->y_offs;
dest_sprite->next = nullptr;
dest_sprite->missing_zoom_levels = 0;
/* Copy over only the 'remap' channel, as that is what we care about in 8bpp */
for (int i = 0; i < sprite->height * sprite->width; i++) {

View File

@@ -24,6 +24,8 @@ Sprite *Blitter_Null::Encode(const SpriteLoader::Sprite *sprite, AllocatorProc *
dest_sprite->width = sprite->width;
dest_sprite->x_offs = sprite->x_offs;
dest_sprite->y_offs = sprite->y_offs;
dest_sprite->next = nullptr;
dest_sprite->missing_zoom_levels = 0;
return dest_sprite;
}